00001
00002
00003 #if defined(_MSC_VER)
00004
00005 # pragma warning(disable:4786)
00006 #endif
00007
00008 #include <cassert>
00009 #include <cmath>
00010 #include <cfloat>
00011 #include <string>
00012 #include <cstdio>
00013 #include <iostream>
00014
00015 #include "CoinMpsIO.hpp"
00016 #include "CoinMessage.hpp"
00017
00018
00019
00020
00021 double osi_strtod(char * ptr, char ** output)
00022 {
00023
00024 static const double fraction[]=
00025 {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,
00026 1.0e-9,1.0e-10,1.0e-11,1.0e-12,1.0e-13,1.0e-14,1.0e-15,1.0e-16,
00027 1.0e-17,1.0e-18,1.0e-19};
00028
00029 static const double exponent[]=
00030 {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,
00031 1.0,1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e6,1.0e7,1.0e8,1.0e9};
00032
00033 double value = 0.0;
00034 char * save = ptr;
00035
00036
00037 while (*ptr==' '||*ptr=='\t')
00038 ptr++;
00039 double sign1=1.0;
00040
00041 if (*ptr=='-') {
00042 sign1=-1.0;
00043 ptr++;
00044 } else if (*ptr=='+') {
00045 ptr++;
00046 }
00047
00048 while (*ptr==' '||*ptr=='\t')
00049 ptr++;
00050 char thisChar=0;
00051 while (value<1.0e30) {
00052 thisChar = *ptr;
00053 ptr++;
00054 if (thisChar>='0'&&thisChar<='9')
00055 value = value*10.0+thisChar-'0';
00056 else
00057 break;
00058 }
00059 if (value<1.0e30) {
00060 if (thisChar=='.') {
00061
00062 double value2 = 0.0;
00063 int nfrac=0;
00064 while (nfrac<20) {
00065 thisChar = *ptr;
00066 ptr++;
00067 if (thisChar>='0'&&thisChar<='9') {
00068 value2 = value2*10.0+thisChar-'0';
00069 nfrac++;
00070 } else {
00071 break;
00072 }
00073 }
00074 if (nfrac<20) {
00075 value += value2*fraction[nfrac];
00076 } else {
00077 thisChar='x';
00078 }
00079 }
00080 if (thisChar=='e'||thisChar=='E') {
00081
00082 int sign2=1;
00083
00084 if (*ptr=='-') {
00085 sign2=-1;
00086 ptr++;
00087 } else if (*ptr=='+') {
00088 ptr++;
00089 }
00090 int value3 = 0;
00091 while (value3<100) {
00092 thisChar = *ptr;
00093 ptr++;
00094 if (thisChar>='0'&&thisChar<='9') {
00095 value3 = value3*10+thisChar-'0';
00096 } else {
00097 break;
00098 }
00099 }
00100 if (value3<200) {
00101 value3 *= sign2;
00102 if (abs(value3)<10) {
00103
00104 value *= exponent[value3+9];
00105 } else {
00106 value *= pow(10.0,value3);
00107 }
00108 } else {
00109 thisChar='x';
00110 }
00111 }
00112 if (thisChar==0||thisChar=='\t'||thisChar==' ') {
00113
00114 *output=ptr;
00115 } else {
00116 *output=save;
00117 }
00118 } else {
00119
00120 *output=save;
00121 }
00122 return value*sign1;
00123 }
00124
00125
00126 const static char *section[] = {
00127 "", "NAME", "ROW", "COLUMN", "RHS", "RANGES", "BOUNDS", "ENDATA", " ","QSECTION", "CSECTION", " "
00128 };
00129
00130
00131 const static COINMpsType startType[] = {
00132 COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
00133 COIN_N_ROW, COIN_BLANK_COLUMN,
00134 COIN_BLANK_COLUMN, COIN_BLANK_COLUMN,
00135 COIN_UP_BOUND, COIN_UNKNOWN_MPS_TYPE,
00136 COIN_UNKNOWN_MPS_TYPE,
00137 COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_UNKNOWN_MPS_TYPE
00138 };
00139 const static COINMpsType endType[] = {
00140 COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
00141 COIN_BLANK_COLUMN, COIN_UNSET_BOUND,
00142 COIN_S1_COLUMN, COIN_S1_COLUMN,
00143 COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
00144 COIN_UNKNOWN_MPS_TYPE,
00145 COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_UNKNOWN_MPS_TYPE
00146 };
00147 const static int allowedLength[] = {
00148 0, 0,
00149 1, 2,
00150 0, 0,
00151 2, 0,
00152 0, 0
00153 };
00154
00155
00156 const static char *mpsTypes[] = {
00157 "N", "E", "L", "G",
00158 " ", "S1", "S2", "S3", " ", " ", " ",
00159 " ", "UP", "FX", "LO", "FR", "MI", "PL", "BV", "UI", "SC"
00160 };
00161
00162 int CoinMpsCardReader::cleanCard()
00163 {
00164 char * getit;
00165 #ifdef COIN_USE_ZLIB
00166 if (fp_) {
00167
00168 getit = fgets ( card_, MAX_CARD_LENGTH, fp_ );
00169 } else {
00170 getit = gzgets ( gzfp_, card_, MAX_CARD_LENGTH );
00171 }
00172 #else
00173
00174 getit = fgets ( card_, MAX_CARD_LENGTH, fp_ );
00175 #endif
00176
00177 if ( getit ) {
00178 cardNumber_++;
00179 unsigned char * lastNonBlank = (unsigned char *) card_-1;
00180 unsigned char * image = (unsigned char *) card_;
00181 while ( *image != '\0' ) {
00182 if ( *image != '\t' && *image < ' ' ) {
00183 break;
00184 } else if ( *image != '\t' && *image != ' ') {
00185 lastNonBlank = image;
00186 }
00187 image++;
00188 }
00189 *(lastNonBlank+1)='\0';
00190 return 0;
00191 } else {
00192 return 1;
00193 }
00194 }
00195
00196 char *
00197 nextBlankOr ( char *image )
00198 {
00199 char * saveImage=image;
00200 while ( 1 ) {
00201 if ( *image == ' ' || *image == '\t' ) {
00202 break;
00203 }
00204 if ( *image == '\0' )
00205 return NULL;
00206 image++;
00207 }
00208
00209 if (image-saveImage==1&&(*saveImage=='+'||*saveImage=='-')) {
00210 while ( *image == ' ' || *image == '\t' ) {
00211 image++;
00212 }
00213 image=nextBlankOr(image);
00214 }
00215 return image;
00216 }
00217
00218
00219 COINSectionType
00220 CoinMpsCardReader::readToNextSection ( )
00221 {
00222 bool found = false;
00223
00224 while ( !found ) {
00225
00226
00227 if ( cleanCard() ) {
00228 section_ = COIN_EOF_SECTION;
00229 break;
00230 }
00231 if ( !strncmp ( card_, "NAME", 4 ) ||
00232 !strncmp( card_, "TIME", 4 ) ||
00233 !strncmp( card_, "STOCH", 5 ) ) {
00234 section_ = COIN_NAME_SECTION;
00235 char *next = card_ + 5;
00236
00237 handler_->message(COIN_MPS_LINE,messages_)<<cardNumber_
00238 <<card_<<CoinMessageEol;
00239 while ( next != eol_ ) {
00240 if ( *next == ' ' || *next == '\t' ) {
00241 next++;
00242 } else {
00243 break;
00244 }
00245 }
00246 if ( next != eol_ ) {
00247 char *nextBlank = nextBlankOr ( next );
00248 char save;
00249
00250 if ( nextBlank ) {
00251 save = *nextBlank;
00252 *nextBlank = '\0';
00253 strcpy ( columnName_, next );
00254 *nextBlank = save;
00255 if ( strstr ( nextBlank, "FREE" ) )
00256 freeFormat_ = true;
00257 } else {
00258 strcpy ( columnName_, next );
00259 }
00260 } else {
00261 strcpy ( columnName_, "no_name" );
00262 }
00263 break;
00264 } else if ( card_[0] != '*' && card_[0] != '#' ) {
00265
00266 int i;
00267
00268 handler_->message(COIN_MPS_LINE,messages_)<<cardNumber_
00269 <<card_<<CoinMessageEol;
00270 for ( i = COIN_ROW_SECTION; i < COIN_UNKNOWN_SECTION; i++ ) {
00271 if ( !strncmp ( card_, section[i], strlen ( section[i] ) ) ) {
00272 break;
00273 }
00274 }
00275 position_ = card_;
00276 eol_ = card_;
00277 section_ = ( COINSectionType ) i;
00278 break;
00279 }
00280 }
00281 return section_;
00282 }
00283
00284 CoinMpsCardReader::CoinMpsCardReader ( FILE * fp , gzFile gzfp, CoinMpsIO * reader)
00285 {
00286 memset ( card_, 0, MAX_CARD_LENGTH );
00287 position_ = card_;
00288 eol_ = card_;
00289 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00290 memset ( rowName_, 0, MAX_FIELD_LENGTH );
00291 memset ( columnName_, 0, MAX_FIELD_LENGTH );
00292 value_ = 0.0;
00293 fp_ = fp;
00294 gzfp_ = gzfp;
00295 section_ = COIN_EOF_SECTION;
00296 cardNumber_ = 0;
00297 freeFormat_ = false;
00298 eightChar_ = true;
00299 reader_ = reader;
00300 handler_ = reader_->messageHandler();
00301 messages_ = reader_->messages();
00302 }
00303
00304 CoinMpsCardReader::~CoinMpsCardReader ( )
00305 {
00306 #ifdef COIN_USE_ZLIB
00307 if (!fp_) {
00308
00309 gzclose(gzfp_);
00310 }
00311 #endif
00312 if (fp_)
00313 fclose ( fp_ );
00314 }
00315
00316 void
00317 strcpyAndCompress ( char *to, const char *from )
00318 {
00319 int n = strlen ( from );
00320 int i;
00321 int nto = 0;
00322
00323 for ( i = 0; i < n; i++ ) {
00324 if ( from[i] != ' ' ) {
00325 to[nto++] = from[i];
00326 }
00327 }
00328 if ( !nto )
00329 to[nto++] = ' ';
00330 to[nto] = '\0';
00331 }
00332
00333
00334 COINSectionType
00335 CoinMpsCardReader::nextField ( )
00336 {
00337 mpsType_ = COIN_BLANK_COLUMN;
00338
00339 char *next = position_;
00340
00341 while ( next != eol_ ) {
00342 if ( *next == ' ' || *next == '\t' ) {
00343 next++;
00344 } else {
00345 break;
00346 }
00347 }
00348 bool gotCard;
00349
00350 if ( next == eol_ ) {
00351 gotCard = false;
00352 } else {
00353 gotCard = true;
00354 }
00355 while ( !gotCard ) {
00356
00357
00358 if ( cleanCard() ) {
00359 return COIN_EOF_SECTION;
00360 }
00361 if ( card_[0] == ' ' ) {
00362
00363 position_ = card_;
00364 eol_ = card_ + strlen ( card_ );
00365
00366
00367 next = card_;
00368 while ( next != eol_ ) {
00369 if ( *next == ' ' || *next == '\t' ) {
00370 next++;
00371 } else {
00372 break;
00373 }
00374 }
00375 if ( next != eol_ ) {
00376 char *nextBlank = nextBlankOr ( next );
00377 int nchar;
00378
00379 if ( nextBlank ) {
00380 nchar = nextBlank - next;
00381 } else {
00382 nchar = -1;
00383 }
00384 mpsType_ = COIN_BLANK_COLUMN;
00385
00386 if ( ( section_ != COIN_RHS_SECTION
00387 && section_ != COIN_RANGES_SECTION )
00388 || freeFormat_ || strncmp ( card_ + 4, " ", 8 ) ) {
00389
00390 if ( section_ == COIN_COLUMN_SECTION
00391 && !strstr ( next, "'MARKER'" ) ) nchar = -1;
00392 if ( nchar == allowedLength[section_] ) {
00393
00394 int i;
00395
00396 for ( i = startType[section_]; i < endType[section_]; i++ ) {
00397 if ( !strncmp ( next, mpsTypes[i], nchar ) ) {
00398 mpsType_ = ( COINMpsType ) i;
00399 break;
00400 }
00401 }
00402 if ( mpsType_ != COIN_BLANK_COLUMN ) {
00403
00404 next = nextBlank;
00405 while ( next != eol_ ) {
00406 if ( *next == ' ' || *next == '\t' ) {
00407 next++;
00408 } else {
00409 break;
00410 }
00411 }
00412 if ( next == eol_ ) {
00413
00414 position_ = eol_;
00415 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00416 } else {
00417 nextBlank = nextBlankOr ( next );
00418 }
00419 }
00420 }
00421 if ( mpsType_ != COIN_UNKNOWN_MPS_TYPE ) {
00422
00423 if ( section_ != COIN_BOUNDS_SECTION ||
00424 freeFormat_ || strncmp ( card_ + 4, " ", 8 ) ) {
00425 char save = '?';
00426
00427 if ( !freeFormat_ && eightChar_ && next == card_ + 4 ) {
00428 if ( eol_ - next >= 8 ) {
00429 if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00430 eightChar_ = false;
00431 } else {
00432 nextBlank = next + 8;
00433 }
00434 if (nextBlank) {
00435 save = *nextBlank;
00436 *nextBlank = '\0';
00437 }
00438 } else {
00439 nextBlank = NULL;
00440 }
00441 } else {
00442 if ( nextBlank ) {
00443 save = *nextBlank;
00444 *nextBlank = '\0';
00445 }
00446 }
00447 strcpyAndCompress ( columnName_, next );
00448 if ( nextBlank ) {
00449 *nextBlank = save;
00450
00451 next = nextBlank;
00452 } else {
00453 next = eol_;
00454 }
00455 } else {
00456
00457 strcpy ( columnName_, " " );
00458 }
00459 while ( next != eol_ ) {
00460 if ( *next == ' ' || *next == '\t' ) {
00461 next++;
00462 } else {
00463 break;
00464 }
00465 }
00466 if ( next == eol_ ) {
00467
00468 position_ = eol_;
00469 value_ = -1.0e100;
00470 if ( section_ != COIN_ROW_SECTION &&
00471 section_!= COIN_CONIC_SECTION)
00472 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00473 else
00474 return section_;
00475 } else {
00476 nextBlank = nextBlankOr ( next );
00477
00478 }
00479 if ( section_ != COIN_ROW_SECTION ) {
00480 char save = '?';
00481
00482 if ( !freeFormat_ && eightChar_ && next == card_ + 14 ) {
00483 if ( eol_ - next >= 8 ) {
00484 if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00485 eightChar_ = false;
00486 } else {
00487 nextBlank = next + 8;
00488 }
00489 save = *nextBlank;
00490 *nextBlank = '\0';
00491 } else {
00492 nextBlank = NULL;
00493 }
00494 } else {
00495 if ( nextBlank ) {
00496 save = *nextBlank;
00497 *nextBlank = '\0';
00498 }
00499 }
00500 strcpyAndCompress ( rowName_, next );
00501 if ( nextBlank ) {
00502 *nextBlank = save;
00503
00504 next = nextBlank;
00505 } else {
00506 next = eol_;
00507 }
00508 while ( next != eol_ ) {
00509 if ( *next == ' ' || *next == '\t' ) {
00510 next++;
00511 } else {
00512 break;
00513 }
00514 }
00515
00516 if ( section_ == COIN_COLUMN_SECTION &&
00517 !strncmp ( rowName_, "'MARKER'", 8 ) && next != eol_ ) {
00518 if ( !strncmp ( next, "'INTORG'", 8 ) ) {
00519 mpsType_ = COIN_INTORG;
00520 } else if ( !strncmp ( next, "'INTEND'", 8 ) ) {
00521 mpsType_ = COIN_INTEND;
00522 } else if ( !strncmp ( next, "'SOSORG'", 8 ) ) {
00523 if ( mpsType_ == COIN_BLANK_COLUMN )
00524 mpsType_ = COIN_S1_COLUMN;
00525 } else if ( !strncmp ( next, "'SOSEND'", 8 ) ) {
00526 mpsType_ = COIN_SOSEND;
00527 } else {
00528 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00529 }
00530 position_ = eol_;
00531 return section_;
00532 }
00533 if ( next == eol_ ) {
00534
00535 position_ = eol_;
00536 if ( section_ != COIN_BOUNDS_SECTION ) {
00537 value_ = -1.0e100;
00538 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00539 } else {
00540 value_ = 0.0;
00541 }
00542 } else {
00543 nextBlank = nextBlankOr ( next );
00544 if ( nextBlank ) {
00545 save = *nextBlank;
00546 *nextBlank = '\0';
00547 }
00548 char * after;
00549 value_ = osi_strtod(next,&after);
00550
00551 assert(after>next);
00552 if ( nextBlank ) {
00553 *nextBlank = save;
00554 position_ = nextBlank;
00555 } else {
00556 position_ = eol_;
00557 }
00558 }
00559 }
00560 }
00561 } else {
00562
00563 strcpy ( columnName_, " " );
00564 char save = '?';
00565
00566 if ( !freeFormat_ && eightChar_ && next == card_ + 14 ) {
00567 if ( eol_ - next >= 8 ) {
00568 if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00569 eightChar_ = false;
00570 } else {
00571 nextBlank = next + 8;
00572 }
00573 save = *nextBlank;
00574 *nextBlank = '\0';
00575 } else {
00576 nextBlank = NULL;
00577 }
00578 } else {
00579 if ( nextBlank ) {
00580 save = *nextBlank;
00581 *nextBlank = '\0';
00582 }
00583 }
00584 strcpyAndCompress ( rowName_, next );
00585 if ( nextBlank ) {
00586 *nextBlank = save;
00587
00588 next = nextBlank;
00589 } else {
00590 next = eol_;
00591 }
00592 while ( next != eol_ ) {
00593 if ( *next == ' ' || *next == '\t' ) {
00594 next++;
00595 } else {
00596 break;
00597 }
00598 }
00599 if ( next == eol_ ) {
00600
00601 position_ = eol_;
00602 value_ = -1.0e100;
00603 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00604 } else {
00605 nextBlank = nextBlankOr ( next );
00606 value_ = -1.0e100;
00607 if ( nextBlank ) {
00608 save = *nextBlank;
00609 *nextBlank = '\0';
00610 }
00611 char * after;
00612 value_ = osi_strtod(next,&after);
00613
00614 assert(after>next);
00615 if ( nextBlank ) {
00616 *nextBlank = save;
00617 position_ = nextBlank;
00618 } else {
00619 position_ = eol_;
00620 }
00621 }
00622 }
00623 }
00624 return section_;
00625 } else if ( card_[0] != '*' ) {
00626
00627 int i;
00628
00629 handler_->message(COIN_MPS_LINE,messages_)<<cardNumber_
00630 <<card_<<CoinMessageEol;
00631 for ( i = COIN_ROW_SECTION; i < COIN_UNKNOWN_SECTION; i++ ) {
00632 if ( !strncmp ( card_, section[i], strlen ( section[i] ) ) ) {
00633 break;
00634 }
00635 }
00636 position_ = card_;
00637 eol_ = card_;
00638 section_ = ( COINSectionType ) i;
00639 return section_;
00640 } else {
00641
00642 }
00643 }
00644
00645 {
00646 char save = '?';
00647 char *nextBlank = nextBlankOr ( next );
00648
00649 if ( !freeFormat_ && eightChar_ && next == card_ + 39 ) {
00650 if ( eol_ - next >= 8 ) {
00651 if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00652 eightChar_ = false;
00653 } else {
00654 nextBlank = next + 8;
00655 }
00656 save = *nextBlank;
00657 *nextBlank = '\0';
00658 } else {
00659 nextBlank = NULL;
00660 }
00661 } else {
00662 if ( nextBlank ) {
00663 save = *nextBlank;
00664 *nextBlank = '\0';
00665 }
00666 }
00667 strcpyAndCompress ( rowName_, next );
00668
00669 if ( nextBlank ) {
00670 *nextBlank = save;
00671 next = nextBlank;
00672 } else {
00673 next = eol_;
00674 }
00675 while ( next != eol_ ) {
00676 if ( *next == ' ' || *next == '\t' ) {
00677 next++;
00678 } else {
00679 break;
00680 }
00681 }
00682 if ( next == eol_ ) {
00683
00684 position_ = eol_;
00685 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00686 } else {
00687 nextBlank = nextBlankOr ( next );
00688 }
00689 if ( nextBlank ) {
00690 save = *nextBlank;
00691 *nextBlank = '\0';
00692 }
00693
00694 char * after;
00695 value_ = osi_strtod(next,&after);
00696
00697 assert(after>next);
00698 if ( nextBlank ) {
00699 *nextBlank = save;
00700 position_ = nextBlank;
00701 } else {
00702 position_ = eol_;
00703 }
00704 }
00705 return section_;
00706 }
00707
00708
00709
00710 static int
00711 hash ( const char *name, int maxsiz, int length )
00712 {
00713 static int mmult[] = {
00714 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
00715 241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
00716 221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
00717 201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
00718 181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
00719 161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
00720 141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
00721 122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
00722 103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
00723 82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
00724 };
00725 int n = 0;
00726 int j;
00727
00728 for ( j = 0; j < length; ++j ) {
00729 int iname = name[j];
00730
00731 n += mmult[j] * iname;
00732 }
00733 return ( abs ( n ) % maxsiz );
00734 }
00735
00736
00737 void
00738 CoinMpsIO::startHash ( char **names, const COINColumnIndex number , int section )
00739 {
00740 names_[section] = names;
00741 numberHash_[section] = number;
00742 startHash(section);
00743 }
00744 void
00745 CoinMpsIO::startHash ( int section ) const
00746 {
00747 char ** names = names_[section];
00748 COINColumnIndex number = numberHash_[section];
00749 COINColumnIndex i;
00750 COINColumnIndex maxhash = 4 * number;
00751 COINColumnIndex ipos, iput;
00752
00753
00754 hash_[section] = new CoinHashLink[maxhash];
00755
00756 CoinHashLink * hashThis = hash_[section];
00757
00758 for ( i = 0; i < maxhash; i++ ) {
00759 hashThis[i].index = -1;
00760 hashThis[i].next = -1;
00761 }
00762
00763
00764
00765
00766
00767
00768 for ( i = 0; i < number; ++i ) {
00769 char *thisName = names[i];
00770 int length = strlen ( thisName );
00771
00772 ipos = hash ( thisName, maxhash, length );
00773 if ( hashThis[ipos].index == -1 ) {
00774 hashThis[ipos].index = i;
00775 }
00776 }
00777
00778
00779
00780
00781
00782
00783
00784 iput = -1;
00785 for ( i = 0; i < number; ++i ) {
00786 char *thisName = names[i];
00787 int length = strlen ( thisName );
00788
00789 ipos = hash ( thisName, maxhash, length );
00790
00791 while ( 1 ) {
00792 COINColumnIndex j1 = hashThis[ipos].index;
00793
00794 if ( j1 == i )
00795 break;
00796 else {
00797 char *thisName2 = names[j1];
00798
00799 if ( strcmp ( thisName, thisName2 ) == 0 ) {
00800 printf ( "** duplicate name %s\n", names[i] );
00801 break;
00802 } else {
00803 COINColumnIndex k = hashThis[ipos].next;
00804
00805 if ( k == -1 ) {
00806 while ( 1 ) {
00807 ++iput;
00808 if ( iput > number ) {
00809 printf ( "** too many names\n" );
00810 break;
00811 }
00812 if ( hashThis[iput].index == -1 ) {
00813 break;
00814 }
00815 }
00816 hashThis[ipos].next = iput;
00817 hashThis[iput].index = i;
00818 break;
00819 } else {
00820 ipos = k;
00821
00822 }
00823 }
00824 }
00825 }
00826 }
00827 }
00828
00829
00830 void
00831 CoinMpsIO::stopHash ( int section )
00832 {
00833 delete [] hash_[section];
00834 hash_[section] = NULL;
00835 }
00836
00837
00838 COINColumnIndex
00839 CoinMpsIO::findHash ( const char *name , int section ) const
00840 {
00841 COINColumnIndex found = -1;
00842
00843 char ** names = names_[section];
00844 CoinHashLink * hashThis = hash_[section];
00845 COINColumnIndex maxhash = 4 * numberHash_[section];
00846 COINColumnIndex ipos;
00847
00848
00849 if ( !maxhash )
00850 return -1;
00851 int length = strlen ( name );
00852
00853 ipos = hash ( name, maxhash, length );
00854 while ( 1 ) {
00855 COINColumnIndex j1 = hashThis[ipos].index;
00856
00857 if ( j1 >= 0 ) {
00858 char *thisName2 = names[j1];
00859
00860 if ( strcmp ( name, thisName2 ) != 0 ) {
00861 COINColumnIndex k = hashThis[ipos].next;
00862
00863 if ( k != -1 )
00864 ipos = k;
00865 else
00866 break;
00867 } else {
00868 found = j1;
00869 break;
00870 }
00871 } else {
00872 found = -1;
00873 break;
00874 }
00875 }
00876 return found;
00877 }
00878
00879
00880
00881
00882 double CoinMpsIO::getInfinity() const
00883 {
00884 return infinity_;
00885 }
00886
00887
00888
00889 void CoinMpsIO::setInfinity(double value)
00890 {
00891 if ( value >= 1.020 ) {
00892 infinity_ = value;
00893 } else {
00894 handler_->message(COIN_MPS_ILLEGAL,messages_)<<"infinity"
00895 <<value
00896 <<CoinMessageEol;
00897 }
00898
00899 }
00900
00901 void CoinMpsIO::setFileName(const char * name)
00902 {
00903 free(fileName_);
00904 fileName_=strdup(name);
00905 }
00906
00907 const char * CoinMpsIO::getFileName() const
00908 {
00909 return fileName_;
00910 }
00911
00912 const bool CoinMpsIO::fileReadable() const
00913 {
00914
00915 FILE *fp;
00916 if (strcmp(fileName_,"stdin")) {
00917 fp = fopen ( fileName_, "r" );
00918 } else {
00919 fp = stdin;
00920 }
00921 if (!fp) {
00922 return false;
00923 } else {
00924 fclose(fp);
00925 return true;
00926 }
00927 }
00928
00929 int
00930 CoinMpsIO::dealWithFileName(const char * filename, const char * extension,
00931 FILE * & fp, gzFile & gzfp)
00932 {
00933 fp=NULL;
00934 int goodFile=0;
00935 gzfp=NULL;
00936 if (!fileName_||(filename!=NULL&&strcmp(filename,fileName_))) {
00937 if (filename==NULL) {
00938 handler_->message(COIN_MPS_FILE,messages_)<<"NULL"
00939 <<CoinMessageEol;
00940 return -1;
00941 }
00942 goodFile=-1;
00943
00944 char newName[400];
00945 if (strcmp(filename,"stdin")&&strcmp(filename,"-")) {
00946 if (extension&&strlen(extension)) {
00947
00948 int i = strlen(filename)-1;
00949 strcpy(newName,filename);
00950 bool foundDot=false;
00951 for (;i>=0;i--) {
00952 char character = filename[i];
00953 if (character=='/'||character=='\\') {
00954 break;
00955 } else if (character=='.') {
00956 foundDot=true;
00957 break;
00958 }
00959 }
00960 if (!foundDot) {
00961 strcat(newName,".");
00962 strcat(newName,extension);
00963 }
00964 } else {
00965
00966 strcpy(newName,filename);
00967 }
00968 } else {
00969 strcpy(newName,"stdin");
00970 }
00971
00972 if (fileName_&&!strcmp(newName,fileName_)) {
00973
00974 return 0;
00975 } else {
00976
00977 free(fileName_);
00978 fileName_=strdup(newName);
00979 if (strcmp(fileName_,"stdin")) {
00980 #ifdef COIN_USE_ZLIB
00981 int length=strlen(fileName_);
00982 if (!strcmp(fileName_+length-3,".gz")) {
00983 gzfp = gzopen(fileName_,"rb");
00984 fp = NULL;
00985 goodFile = (gzfp!=NULL);
00986 } else {
00987 #endif
00988 fp = fopen ( fileName_, "r" );
00989 if (fp!=NULL)
00990 goodFile=1;
00991 #ifdef COIN_USE_ZLIB
00992 if (goodFile<0) {
00993 std::string fname(fileName_);
00994 fname += ".gz";
00995 gzfp = gzopen(fname.c_str(),"rb");
00996 printf("%s\n", fname.c_str());
00997 if (gzfp!=NULL)
00998 goodFile=1;
00999 }
01000 }
01001 #endif
01002 } else {
01003 fp = stdin;
01004 goodFile = 1;
01005 }
01006 }
01007 } else {
01008
01009
01010 goodFile=0;
01011 }
01012 if (goodFile<0)
01013 handler_->message(COIN_MPS_FILE,messages_)<<fileName_
01014 <<CoinMessageEol;
01015 return goodFile;
01016 }
01017
01018 double CoinMpsIO::objectiveOffset() const
01019 {
01020 return objectiveOffset_;
01021 }
01022 #define MAX_INTEGER 1000000
01023
01024 void CoinMpsIO::setDefaultBound(int value)
01025 {
01026 if ( value >= 1 && value <=MAX_INTEGER ) {
01027 defaultBound_ = value;
01028 } else {
01029 handler_->message(COIN_MPS_ILLEGAL,messages_)<<"default integer bound"
01030 <<value
01031 <<CoinMessageEol;
01032 }
01033 }
01034
01035 int CoinMpsIO::getDefaultBound() const
01036 {
01037 return defaultBound_;
01038 }
01039
01040
01041
01042 int CoinMpsIO::readMps(const char * filename, const char * extension)
01043 {
01044
01045 FILE *fp=NULL;
01046 gzFile gzfp=NULL;
01047 int returnCode = dealWithFileName(filename,extension,fp,gzfp);
01048 if (returnCode<0) {
01049 return -1;
01050 } else if (returnCode>0) {
01051 delete cardReader_;
01052 cardReader_ = new CoinMpsCardReader ( fp , gzfp, this);
01053 }
01054 return readMps();
01055 }
01056 int CoinMpsIO::readMps()
01057 {
01058 bool ifmps;
01059
01060 cardReader_->readToNextSection();
01061
01062 if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION ) {
01063 ifmps = true;
01064
01065 free(problemName_);
01066 problemName_=strdup(cardReader_->columnName());
01067 } else if ( cardReader_->whichSection ( ) == COIN_UNKNOWN_SECTION ) {
01068 handler_->message(COIN_MPS_BADFILE1,messages_)<<cardReader_->card()
01069 <<1
01070 <<fileName_
01071 <<CoinMessageEol;
01072 #ifdef COIN_USE_ZLIB
01073 if (!cardReader_->filePointer())
01074 handler_->message(COIN_MPS_BADFILE2,messages_)<<CoinMessageEol;
01075
01076 #endif
01077 return -2;
01078 } else if ( cardReader_->whichSection ( ) != COIN_EOF_SECTION ) {
01079
01080 free(problemName_);
01081 problemName_=strdup(cardReader_->card());
01082 ifmps = false;
01083 } else {
01084 handler_->message(COIN_MPS_EOF,messages_)<<fileName_
01085 <<CoinMessageEol;
01086 return -3;
01087 }
01088 CoinBigIndex *start;
01089 COINRowIndex *row;
01090 double *element;
01091 objectiveOffset_ = 0.0;
01092
01093 int numberErrors = 0;
01094 int i;
01095
01096 if ( ifmps ) {
01097
01098 bool gotNrow = false;
01099
01100
01101 cardReader_->nextField ( ) ;
01102
01103 if (!strncmp(cardReader_->card(),"OBJSENSE",8)) {
01104 cardReader_->nextField();
01105 int i;
01106 const char * thisCard = cardReader_->card();
01107 int direction = 0;
01108 for (i=0;i<20;i++) {
01109 if (thisCard[i]!=' ') {
01110 if (!strncmp(thisCard+i,"MAX",3))
01111 direction=-1;
01112 else if (!strncmp(thisCard+i,"MIN",3))
01113 direction=1;
01114 break;
01115 }
01116 }
01117 if (!direction)
01118 printf("No MAX/MIN found after OBJSENSE\n");
01119 else
01120 printf("%s found after OBJSENSE - Coin ignores\n",
01121 (direction>0 ? "MIN" : "MAX"));
01122 cardReader_->nextField();
01123 }
01124 if ( cardReader_->whichSection ( ) != COIN_ROW_SECTION ) {
01125 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01126 <<cardReader_->card()
01127 <<CoinMessageEol;
01128 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01129 return numberErrors;
01130 }
01131
01132 numberRows_ = 0;
01133 numberColumns_ = 0;
01134 numberElements_ = 0;
01135 COINRowIndex maxRows = 1000;
01136 COINMpsType *rowType =
01137
01138 ( COINMpsType * ) malloc ( maxRows * sizeof ( COINMpsType ) );
01139 char **rowName = ( char ** ) malloc ( maxRows * sizeof ( char * ) );
01140
01141
01142 COINRowIndex maxFreeRows = 100;
01143 COINRowIndex numberOtherFreeRows = 0;
01144 char **freeRowName =
01145
01146 ( char ** ) malloc ( maxFreeRows * sizeof ( char * ) );
01147 while ( cardReader_->nextField ( ) == COIN_ROW_SECTION ) {
01148 switch ( cardReader_->mpsType ( ) ) {
01149 case COIN_N_ROW:
01150 if ( !gotNrow ) {
01151 gotNrow = true;
01152
01153 free(objectiveName_);
01154 objectiveName_=strdup(cardReader_->columnName());
01155 } else {
01156
01157 if ( numberOtherFreeRows == maxFreeRows ) {
01158 maxFreeRows = ( 3 * maxFreeRows ) / 2 + 100;
01159 freeRowName =
01160 ( char ** ) realloc ( freeRowName,
01161
01162 maxFreeRows * sizeof ( char * ) );
01163 }
01164 freeRowName[numberOtherFreeRows] =
01165 strdup ( cardReader_->columnName ( ) );
01166 numberOtherFreeRows++;
01167 }
01168 break;
01169 case COIN_E_ROW:
01170 case COIN_L_ROW:
01171 case COIN_G_ROW:
01172 if ( numberRows_ == maxRows ) {
01173 maxRows = ( 3 * maxRows ) / 2 + 1000;
01174 rowType =
01175 ( COINMpsType * ) realloc ( rowType,
01176 maxRows * sizeof ( COINMpsType ) );
01177 rowName =
01178
01179 ( char ** ) realloc ( rowName, maxRows * sizeof ( char * ) );
01180 }
01181 rowType[numberRows_] = cardReader_->mpsType ( );
01182 rowName[numberRows_] = strdup ( cardReader_->columnName ( ) );
01183 numberRows_++;
01184 break;
01185 default:
01186 numberErrors++;
01187 if ( numberErrors < 100 ) {
01188 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01189 <<cardReader_->card()
01190 <<CoinMessageEol;
01191 } else if (numberErrors > 100000) {
01192 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01193 return numberErrors;
01194 }
01195 }
01196 }
01197 if ( cardReader_->whichSection ( ) != COIN_COLUMN_SECTION ) {
01198 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01199 <<cardReader_->card()
01200 <<CoinMessageEol;
01201 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01202 return numberErrors;
01203 }
01204 assert ( gotNrow );
01205 rowType =
01206 ( COINMpsType * ) realloc ( rowType,
01207 numberRows_ * sizeof ( COINMpsType ) );
01208
01209 rowName =
01210 ( char ** ) realloc ( rowName,
01211 ( numberRows_ + 1 +
01212
01213 numberOtherFreeRows ) * sizeof ( char * ) );
01214 rowName[numberRows_] = strdup(objectiveName_);
01215 memcpy ( rowName + numberRows_ + 1, freeRowName,
01216 numberOtherFreeRows * sizeof ( char * ) );
01217
01218 free(freeRowName);
01219
01220 startHash ( rowName, numberRows_ + 1 + numberOtherFreeRows , 0 );
01221 COINColumnIndex maxColumns = 1000 + numberRows_ / 5;
01222 CoinBigIndex maxElements = 5000 + numberRows_ / 2;
01223 COINMpsType *columnType = ( COINMpsType * )
01224 malloc ( maxColumns * sizeof ( COINMpsType ) );
01225 char **columnName = ( char ** ) malloc ( maxColumns * sizeof ( char * ) );
01226
01227 objective_ = ( double * ) malloc ( maxColumns * sizeof ( double ) );
01228 start = ( CoinBigIndex * )
01229 malloc ( ( maxColumns + 1 ) * sizeof ( CoinBigIndex ) );
01230 row = ( COINRowIndex * )
01231 malloc ( maxElements * sizeof ( COINRowIndex ) );
01232 element =
01233 ( double * ) malloc ( maxElements * sizeof ( double ) );
01234
01235 CoinBigIndex *rowUsed = new CoinBigIndex[numberRows_];
01236
01237 for (i=0;i<numberRows_;i++) {
01238 rowUsed[i]=-1;
01239 }
01240 bool objUsed = false;
01241
01242 numberElements_ = 0;
01243 char lastColumn[200];
01244
01245 memset ( lastColumn, '\0', 200 );
01246 COINColumnIndex column = -1;
01247 bool inIntegerSet = false;
01248 COINColumnIndex numberIntegers = 0;
01249 const double tinyElement = 1.0e-14;
01250
01251 while ( cardReader_->nextField ( ) == COIN_COLUMN_SECTION ) {
01252 switch ( cardReader_->mpsType ( ) ) {
01253 case COIN_BLANK_COLUMN:
01254 if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) {
01255
01256
01257
01258 if ( numberColumns_ ) {
01259 objUsed = false;
01260 CoinBigIndex i;
01261 CoinBigIndex k = start[column];
01262
01263 for ( i = k; i < numberElements_; i++ ) {
01264 COINRowIndex irow = row[i];
01265 #if 0
01266 if ( fabs ( element[i] ) > tinyElement ) {
01267 element[k++] = element[i];
01268 }
01269 #endif
01270 rowUsed[irow] = -1;
01271 }
01272
01273 }
01274 column = numberColumns_;
01275 if ( numberColumns_ == maxColumns ) {
01276 maxColumns = ( 3 * maxColumns ) / 2 + 1000;
01277 columnType = ( COINMpsType * )
01278 realloc ( columnType, maxColumns * sizeof ( COINMpsType ) );
01279 columnName = ( char ** )
01280 realloc ( columnName, maxColumns * sizeof ( char * ) );
01281
01282 objective_ = ( double * )
01283 realloc ( objective_, maxColumns * sizeof ( double ) );
01284 start = ( CoinBigIndex * )
01285 realloc ( start,
01286 ( maxColumns + 1 ) * sizeof ( CoinBigIndex ) );
01287 }
01288 if ( !inIntegerSet ) {
01289 columnType[column] = COIN_UNSET_BOUND;
01290 } else {
01291 columnType[column] = COIN_INTORG;
01292 numberIntegers++;
01293 }
01294 columnName[column] = strdup ( cardReader_->columnName ( ) );
01295 strcpy ( lastColumn, cardReader_->columnName ( ) );
01296 objective_[column] = 0.0;
01297 start[column] = numberElements_;
01298 numberColumns_++;
01299 }
01300 if ( fabs ( cardReader_->value ( ) ) > tinyElement ) {
01301 if ( numberElements_ == maxElements ) {
01302 maxElements = ( 3 * maxElements ) / 2 + 1000;
01303 row = ( COINRowIndex * )
01304 realloc ( row, maxElements * sizeof ( COINRowIndex ) );
01305 element = ( double * )
01306 realloc ( element, maxElements * sizeof ( double ) );
01307 }
01308
01309 COINRowIndex irow = findHash ( cardReader_->rowName ( ) , 0 );
01310
01311 if ( irow >= 0 ) {
01312 double value = cardReader_->value ( );
01313
01314
01315 if ( irow == numberRows_ ) {
01316
01317 if ( objUsed ) {
01318 numberErrors++;
01319 if ( numberErrors < 100 ) {
01320 handler_->message(COIN_MPS_DUPOBJ,messages_)
01321 <<cardReader_->cardNumber()<<cardReader_->card()
01322 <<CoinMessageEol;
01323 } else if (numberErrors > 100000) {
01324 handler_->message(COIN_MPS_RETURNING,messages_)
01325 <<CoinMessageEol;
01326 return numberErrors;
01327 }
01328 } else {
01329 objUsed = true;
01330 }
01331 value += objective_[column];
01332 if ( fabs ( value ) <= tinyElement )
01333 value = 0.0;
01334 objective_[column] = value;
01335 } else if ( irow < numberRows_ ) {
01336
01337 if ( rowUsed[irow] >= 0 ) {
01338 element[rowUsed[irow]] += value;
01339 numberErrors++;
01340 if ( numberErrors < 100 ) {
01341 handler_->message(COIN_MPS_DUPROW,messages_)
01342 <<cardReader_->rowName()<<cardReader_->cardNumber()
01343 <<cardReader_->card()
01344 <<CoinMessageEol;
01345 } else if (numberErrors > 100000) {
01346 handler_->message(COIN_MPS_RETURNING,messages_)
01347 <<CoinMessageEol;
01348 return numberErrors;
01349 }
01350 } else {
01351 row[numberElements_] = irow;
01352 element[numberElements_] = value;
01353 rowUsed[irow] = numberElements_;
01354 numberElements_++;
01355 }
01356 }
01357 } else {
01358 numberErrors++;
01359 if ( numberErrors < 100 ) {
01360 handler_->message(COIN_MPS_NOMATCHROW,messages_)
01361 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01362 <<CoinMessageEol;
01363 } else if (numberErrors > 100000) {
01364 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01365 return numberErrors;
01366 }
01367 }
01368 }
01369 break;
01370 case COIN_INTORG:
01371 inIntegerSet = true;
01372 break;
01373 case COIN_INTEND:
01374 inIntegerSet = false;
01375 break;
01376 case COIN_S1_COLUMN:
01377 case COIN_S2_COLUMN:
01378 case COIN_S3_COLUMN:
01379 case COIN_SOSEND:
01380 std::cout << "** code sos etc later" << std::endl;
01381 abort ( );
01382 break;
01383 default:
01384 numberErrors++;
01385 if ( numberErrors < 100 ) {
01386 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01387 <<cardReader_->card()
01388 <<CoinMessageEol;
01389 } else if (numberErrors > 100000) {
01390 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01391 return numberErrors;
01392 }
01393 }
01394 }
01395 start[numberColumns_] = numberElements_;
01396 delete[]rowUsed;
01397 if ( cardReader_->whichSection ( ) != COIN_RHS_SECTION ) {
01398 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01399 <<cardReader_->card()
01400 <<CoinMessageEol;
01401 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01402 return numberErrors;
01403 }
01404 columnType =
01405 ( COINMpsType * ) realloc ( columnType,
01406 numberColumns_ * sizeof ( COINMpsType ) );
01407 columnName =
01408
01409 ( char ** ) realloc ( columnName, numberColumns_ * sizeof ( char * ) );
01410 objective_ = ( double * )
01411 realloc ( objective_, numberColumns_ * sizeof ( double ) );
01412 start = ( CoinBigIndex * )
01413 realloc ( start, ( numberColumns_ + 1 ) * sizeof ( CoinBigIndex ) );
01414 row = ( COINRowIndex * )
01415 realloc ( row, numberElements_ * sizeof ( COINRowIndex ) );
01416 element = ( double * )
01417 realloc ( element, numberElements_ * sizeof ( double ) );
01418
01419 rowlower_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01420 rowupper_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01421 for (i=0;i<numberRows_;i++) {
01422 rowlower_[i]=-infinity_;
01423 rowupper_[i]=infinity_;
01424 }
01425 objUsed = false;
01426 memset ( lastColumn, '\0', 200 );
01427 bool gotRhs = false;
01428
01429
01430 while ( cardReader_->nextField ( ) == COIN_RHS_SECTION ) {
01431 COINRowIndex irow;
01432
01433 switch ( cardReader_->mpsType ( ) ) {
01434 case COIN_BLANK_COLUMN:
01435 if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) {
01436
01437
01438 if ( gotRhs ) {
01439 while ( cardReader_->nextField ( ) == COIN_RHS_SECTION ) {
01440 }
01441 break;
01442 } else {
01443 gotRhs = true;
01444 strcpy ( lastColumn, cardReader_->columnName ( ) );
01445
01446 free(rhsName_);
01447 rhsName_=strdup(cardReader_->columnName());
01448 }
01449 }
01450
01451 irow = findHash ( cardReader_->rowName ( ) , 0 );
01452 if ( irow >= 0 ) {
01453 double value = cardReader_->value ( );
01454
01455
01456 if ( irow == numberRows_ ) {
01457
01458 if ( objUsed ) {
01459 numberErrors++;
01460 if ( numberErrors < 100 ) {
01461 handler_->message(COIN_MPS_DUPOBJ,messages_)
01462 <<cardReader_->cardNumber()<<cardReader_->card()
01463 <<CoinMessageEol;
01464 } else if (numberErrors > 100000) {
01465 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01466 return numberErrors;
01467 }
01468 } else {
01469 objUsed = true;
01470 }
01471 objectiveOffset_ += value;
01472 } else if ( irow < numberRows_ ) {
01473 if ( rowlower_[irow] != -infinity_ ) {
01474 numberErrors++;
01475 if ( numberErrors < 100 ) {
01476 handler_->message(COIN_MPS_DUPROW,messages_)
01477 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01478 <<CoinMessageEol;
01479 } else if (numberErrors > 100000) {
01480 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01481 return numberErrors;
01482 }
01483 } else {
01484 rowlower_[irow] = value;
01485 }
01486 }
01487 } else {
01488 numberErrors++;
01489 if ( numberErrors < 100 ) {
01490 handler_->message(COIN_MPS_NOMATCHROW,messages_)
01491 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01492 <<CoinMessageEol;
01493 } else if (numberErrors > 100000) {
01494 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01495 return numberErrors;
01496 }
01497 }
01498 break;
01499 default:
01500 numberErrors++;
01501 if ( numberErrors < 100 ) {
01502 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01503 <<cardReader_->card()
01504 <<CoinMessageEol;
01505 } else if (numberErrors > 100000) {
01506 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01507 return numberErrors;
01508 }
01509 }
01510 }
01511 if ( cardReader_->whichSection ( ) == COIN_RANGES_SECTION ) {
01512 memset ( lastColumn, '\0', 200 );
01513 bool gotRange = false;
01514 COINRowIndex irow;
01515
01516
01517 while ( cardReader_->nextField ( ) == COIN_RANGES_SECTION ) {
01518 switch ( cardReader_->mpsType ( ) ) {
01519 case COIN_BLANK_COLUMN:
01520 if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) {
01521
01522
01523 if ( gotRange ) {
01524 while ( cardReader_->nextField ( ) == COIN_RANGES_SECTION ) {
01525 }
01526 break;
01527 } else {
01528 gotRange = true;
01529 strcpy ( lastColumn, cardReader_->columnName ( ) );
01530
01531 free(rangeName_);
01532 rangeName_=strdup(cardReader_->columnName());
01533 }
01534 }
01535
01536 irow = findHash ( cardReader_->rowName ( ) , 0 );
01537 if ( irow >= 0 ) {
01538 double value = cardReader_->value ( );
01539
01540
01541 if ( irow == numberRows_ ) {
01542
01543 numberErrors++;
01544 if ( numberErrors < 100 ) {
01545 handler_->message(COIN_MPS_DUPOBJ,messages_)
01546 <<cardReader_->cardNumber()<<cardReader_->card()
01547 <<CoinMessageEol;
01548 } else if (numberErrors > 100000) {
01549 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01550 return numberErrors;
01551 }
01552 } else {
01553 if ( rowupper_[irow] != infinity_ ) {
01554 numberErrors++;
01555 if ( numberErrors < 100 ) {
01556 handler_->message(COIN_MPS_DUPROW,messages_)
01557 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01558 <<CoinMessageEol;
01559 } else if (numberErrors > 100000) {
01560 handler_->message(COIN_MPS_RETURNING,messages_)
01561 <<CoinMessageEol;
01562 return numberErrors;
01563 }
01564 } else {
01565 rowupper_[irow] = value;
01566 }
01567 }
01568 } else {
01569 numberErrors++;
01570 if ( numberErrors < 100 ) {
01571 handler_->message(COIN_MPS_NOMATCHROW,messages_)
01572 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01573 <<CoinMessageEol;
01574 } else if (numberErrors > 100000) {
01575 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01576 return numberErrors;
01577 }
01578 }
01579 break;
01580 default:
01581 numberErrors++;
01582 if ( numberErrors < 100 ) {
01583 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01584 <<cardReader_->card()
01585 <<CoinMessageEol;
01586 } else if (numberErrors > 100000) {
01587 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01588 return numberErrors;
01589 }
01590 }
01591 }
01592 }
01593 stopHash ( 0 );
01594
01595 {
01596 COINRowIndex irow;
01597
01598 for ( irow = 0; irow < numberRows_; irow++ ) {
01599 double lo = rowlower_[irow];
01600 double up = rowupper_[irow];
01601 double up2 = rowupper_[irow];
01602
01603 switch ( rowType[irow] ) {
01604 case COIN_E_ROW:
01605 if ( lo == -infinity_ )
01606 lo = 0.0;
01607 if ( up == infinity_ ) {
01608 up = lo;
01609 } else if ( up > 0.0 ) {
01610 up += lo;
01611 } else {
01612 up = lo;
01613 lo += up2;
01614 }
01615 break;
01616 case COIN_L_ROW:
01617 if ( lo == -infinity_ ) {
01618 up = 0.0;
01619 } else {
01620 up = lo;
01621 lo = -infinity_;
01622 }
01623 if ( up2 != infinity_ ) {
01624 lo = up - fabs ( up2 );
01625 }
01626 break;
01627 case COIN_G_ROW:
01628 if ( lo == -infinity_ ) {
01629 lo = 0.0;
01630 up = infinity_;
01631 } else {
01632 up = infinity_;
01633 }
01634 if ( up2 != infinity_ ) {
01635 up = lo + fabs ( up2 );
01636 }
01637 break;
01638 default:
01639 abort();
01640 }
01641 rowlower_[irow] = lo;
01642 rowupper_[irow] = up;
01643 }
01644 }
01645 free ( rowType );
01646
01647 collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01648 colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01649 for (i=0;i<numberColumns_;i++) {
01650 collower_[i]=0.0;
01651 colupper_[i]=infinity_;
01652 }
01653
01654 integerType_ = (char *) malloc (numberColumns_*sizeof(char));
01655
01656 for ( column = 0; column < numberColumns_; column++ ) {
01657 if ( columnType[column] == COIN_INTORG ) {
01658 columnType[column] = COIN_UNSET_BOUND;
01659 integerType_[column] = 1;
01660 } else {
01661 integerType_[column] = 0;
01662 }
01663 }
01664
01665 startHash ( columnName, numberColumns_ , 1 );
01666 if ( cardReader_->whichSection ( ) == COIN_BOUNDS_SECTION ) {
01667 memset ( lastColumn, '\0', 200 );
01668 bool gotBound = false;
01669
01670 while ( cardReader_->nextField ( ) == COIN_BOUNDS_SECTION ) {
01671 if ( strcmp ( lastColumn, cardReader_->columnName ( ) ) ) {
01672
01673
01674 if ( gotBound ) {
01675 while ( cardReader_->nextField ( ) == COIN_BOUNDS_SECTION ) {
01676 }
01677 break;
01678 } else {
01679 gotBound = true;;
01680 strcpy ( lastColumn, cardReader_->columnName ( ) );
01681
01682 free(boundName_);
01683 boundName_=strdup(cardReader_->columnName());
01684 }
01685 }
01686
01687 COINColumnIndex icolumn = findHash ( cardReader_->rowName ( ) , 1 );
01688
01689 if ( icolumn >= 0 ) {
01690 double value = cardReader_->value ( );
01691 bool ifError = false;
01692
01693 switch ( cardReader_->mpsType ( ) ) {
01694 case COIN_UP_BOUND:
01695 if ( value == -1.0e100 )
01696 ifError = true;
01697 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01698 if ( value < 0.0 ) {
01699 collower_[icolumn] = -infinity_;
01700 }
01701 } else if ( columnType[icolumn] == COIN_LO_BOUND ) {
01702 if ( value < collower_[icolumn] ) {
01703 ifError = true;
01704 } else if ( value < collower_[icolumn] + tinyElement ) {
01705 value = collower_[icolumn];
01706 }
01707 } else if ( columnType[icolumn] == COIN_MI_BOUND ) {
01708 } else {
01709 ifError = true;
01710 }
01711 colupper_[icolumn] = value;
01712 columnType[icolumn] = COIN_UP_BOUND;
01713 break;
01714 case COIN_LO_BOUND:
01715 if ( value == -1.0e100 )
01716 ifError = true;
01717 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01718 } else if ( columnType[icolumn] == COIN_UP_BOUND ||
01719 columnType[icolumn] == COIN_UI_BOUND ) {
01720 if ( value > colupper_[icolumn] ) {
01721 ifError = true;
01722 } else if ( value > colupper_[icolumn] - tinyElement ) {
01723 value = colupper_[icolumn];
01724 }
01725 } else {
01726 ifError = true;
01727 }
01728 collower_[icolumn] = value;
01729 columnType[icolumn] = COIN_LO_BOUND;
01730 break;
01731 case COIN_FX_BOUND:
01732 if ( value == -1.0e100 )
01733 ifError = true;
01734 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01735 } else if ( columnType[icolumn] == COIN_UI_BOUND ||
01736 columnType[icolumn] == COIN_BV_BOUND) {
01737
01738 double value2 = floor(value);
01739 if (fabs(value2-value)>1.0e-12||
01740 value2<collower_[icolumn]||
01741 value2>colupper_[icolumn]) {
01742 ifError=true;
01743 } else {
01744
01745 assert(integerType_[icolumn] );
01746 numberIntegers--;
01747 integerType_[icolumn] = 0;
01748 }
01749 } else {
01750 ifError = true;
01751 }
01752 collower_[icolumn] = value;
01753 colupper_[icolumn] = value;
01754 columnType[icolumn] = COIN_FX_BOUND;
01755 break;
01756 case COIN_FR_BOUND:
01757 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01758 } else {
01759 ifError = true;
01760 }
01761 collower_[icolumn] = -infinity_;
01762 colupper_[icolumn] = infinity_;
01763 columnType[icolumn] = COIN_FR_BOUND;
01764 break;
01765 case COIN_MI_BOUND:
01766 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01767 colupper_[icolumn] = COIN_DBL_MAX;
01768 } else if ( columnType[icolumn] == COIN_UP_BOUND ) {
01769 } else {
01770 ifError = true;
01771 }
01772 collower_[icolumn] = -infinity_;
01773 columnType[icolumn] = COIN_MI_BOUND;
01774 break;
01775 case COIN_PL_BOUND:
01776 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01777 } else {
01778 ifError = true;
01779 }
01780 columnType[icolumn] = COIN_PL_BOUND;
01781 break;
01782 case COIN_UI_BOUND:
01783 #if 0
01784 if ( value == -1.0e100 )
01785 ifError = true;
01786 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01787 } else if ( columnType[icolumn] == COIN_LO_BOUND ) {
01788 if ( value < collower_[icolumn] ) {
01789 ifError = true;
01790 } else if ( value < collower_[icolumn] + tinyElement ) {
01791 value = collower_[icolumn];
01792 }
01793 } else {
01794 ifError = true;
01795 }
01796 #else
01797 if ( value == -1.0e100 ) {
01798 value = infinity_;
01799 if (columnType[icolumn] != COIN_UNSET_BOUND &&
01800 columnType[icolumn] != COIN_LO_BOUND) {
01801 ifError = true;
01802 }
01803 } else {
01804 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01805 } else if ( columnType[icolumn] == COIN_LO_BOUND ) {
01806 if ( value < collower_[icolumn] ) {
01807 ifError = true;
01808 } else if ( value < collower_[icolumn] + tinyElement ) {
01809 value = collower_[icolumn];
01810 }
01811 } else {
01812 ifError = true;
01813 }
01814 }
01815 #endif
01816 colupper_[icolumn] = value;
01817 columnType[icolumn] = COIN_UI_BOUND;
01818 if ( !integerType_[icolumn] ) {
01819 numberIntegers++;
01820 integerType_[icolumn] = 1;
01821 }
01822 break;
01823 case COIN_BV_BOUND:
01824 if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01825 } else {
01826 ifError = true;
01827 }
01828 collower_[icolumn] = 0.0;
01829 colupper_[icolumn] = 1.0;
01830 columnType[icolumn] = COIN_BV_BOUND;
01831 if ( !integerType_[icolumn] ) {
01832 numberIntegers++;
01833 integerType_[icolumn] = 1;
01834 }
01835 break;
01836 default:
01837 ifError = true;
01838 break;
01839 }
01840 if ( ifError ) {
01841 numberErrors++;
01842 if ( numberErrors < 100 ) {
01843 handler_->message(COIN_MPS_BADIMAGE,messages_)
01844 <<cardReader_->cardNumber()
01845 <<cardReader_->card()
01846 <<CoinMessageEol;
01847 } else if (numberErrors > 100000) {
01848 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01849 return numberErrors;
01850 }
01851 }
01852 } else {
01853 numberErrors++;
01854 if ( numberErrors < 100 ) {
01855 handler_->message(COIN_MPS_NOMATCHCOL,messages_)
01856 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01857 <<CoinMessageEol;
01858 } else if (numberErrors > 100000) {
01859 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01860 return numberErrors;
01861 }
01862 }
01863 }
01864 }
01865 stopHash ( 1 );
01866
01867 if ( !numberIntegers ) {
01868 free(integerType_);
01869 integerType_ = NULL;
01870 } else {
01871 COINColumnIndex icolumn;
01872
01873 for ( icolumn = 0; icolumn < numberColumns_; icolumn++ ) {
01874 if ( integerType_[icolumn] ) {
01875 assert ( collower_[icolumn] >= -MAX_INTEGER );
01876
01877 if ( columnType[icolumn] == COIN_UNSET_BOUND )
01878 colupper_[icolumn] = defaultBound_;
01879 if ( colupper_[icolumn] > MAX_INTEGER )
01880 colupper_[icolumn] = MAX_INTEGER;
01881 }
01882 }
01883 }
01884 free ( columnType );
01885 if ( cardReader_->whichSection ( ) != COIN_ENDATA_SECTION ) {
01886 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01887 <<cardReader_->card()
01888 <<CoinMessageEol;
01889 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01890 return numberErrors;
01891 }
01892 } else {
01893
01894 COINColumnIndex i;
01895 FILE * fp = cardReader_->filePointer();
01896 fscanf ( fp, "%d %d %d\n", &numberRows_, &numberColumns_, &i);
01897 numberElements_ = i;
01898
01899 rowlower_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01900 rowupper_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01901 for ( i = 0; i < numberRows_; i++ ) {
01902 int j;
01903
01904 fscanf ( fp, "%d %lg %lg\n", &j, &rowlower_[i], &rowupper_[i] );
01905 assert ( i == j );
01906 }
01907 collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01908 colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01909 objective_= ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01910 start = ( CoinBigIndex *) malloc ((numberColumns_ + 1) *
01911 sizeof (CoinBigIndex) );
01912 row = ( COINRowIndex * ) malloc (numberElements_ * sizeof (COINRowIndex));
01913 element = ( double * ) malloc (numberElements_ * sizeof (double) );
01914
01915 start[0] = 0;
01916 numberElements_ = 0;
01917 for ( i = 0; i < numberColumns_; i++ ) {
01918 int j;
01919 int n;
01920
01921 fscanf ( fp, "%d %d %lg %lg %lg\n", &j, &n, &collower_[i], &colupper_[i],
01922 &objective_[i] );
01923 assert ( i == j );
01924 for ( j = 0; j < n; j++ ) {
01925 fscanf ( fp, " %d %lg\n", &row[numberElements_],
01926 &element[numberElements_] );
01927 numberElements_++;
01928 }
01929 start[i + 1] = numberElements_;
01930 }
01931 }
01932
01933 matrixByColumn_ =
01934 new CoinPackedMatrix(true,
01935 numberRows_,numberColumns_,numberElements_,
01936 element,row,start,NULL);
01937 free ( row );
01938 free ( start );
01939 free ( element );
01940
01941 handler_->message(COIN_MPS_STATS,messages_)<<problemName_
01942 <<numberRows_
01943 <<numberColumns_
01944 <<numberElements_
01945 <<CoinMessageEol;
01946 return numberErrors;
01947 }
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959 static void
01960 convertDouble(int formatType, double value, char outputValue[20],
01961 const char * name, char outputRow[100])
01962 {
01963 assert (formatType!=2);
01964 if ((formatType&3)==0) {
01965 bool stripZeros=true;
01966 if (fabs(value)<1.0e40) {
01967 int power10, decimal;
01968 if (value>=0.0) {
01969 power10 =(int) log10(value);
01970 if (power10<9&&power10>-4) {
01971 decimal = min(10,10-power10);
01972 char format[7];
01973 sprintf(format,"%%12.%df",decimal);
01974 sprintf(outputValue,format,value);
01975 } else {
01976 sprintf(outputValue,"%12.7g",value);
01977 stripZeros=false;
01978 }
01979 } else {
01980 power10 =(int) log10(-value)+1;
01981 if (power10<8&&power10>-3) {
01982 decimal = min(9,9-power10);
01983 char format[7];
01984 sprintf(format,"%%12.%df",decimal);
01985 sprintf(outputValue,format,value);
01986 } else {
01987 sprintf(outputValue,"%12.6g",value);
01988 stripZeros=false;
01989 }
01990 }
01991 if (stripZeros) {
01992
01993 int j;
01994 for (j=11;j>=0;j--) {
01995 if (outputValue[j]=='0')
01996 outputValue[j]=' ';
01997 else
01998 break;
01999 }
02000 }
02001 } else {
02002 outputValue[0]= '\0';
02003 }
02004 } else {
02005 if (fabs(value<1.0e40)) {
02006 sprintf(outputValue,"%19g",value);
02007
02008 int i=0;
02009 int j;
02010 for (j=0;j<19;j++) {
02011 if (outputValue[j]!=' ')
02012 outputValue[i++]=outputValue[j];
02013 }
02014 outputValue[i]='\0';
02015 } else {
02016 outputValue[0]= '\0';
02017 }
02018 }
02019 strcpy(outputRow,name);
02020 if (!formatType) {
02021 int i;
02022
02023 for (i=0;i<12;i++) {
02024 if (outputValue[i]=='\0')
02025 break;
02026 }
02027 for (;i<12;i++)
02028 outputValue[i]=' ';
02029 outputValue[12]='\0';
02030 for (i=0;i<8;i++) {
02031 if (outputRow[i]=='\0')
02032 break;
02033 }
02034 for (;i<8;i++)
02035 outputRow[i]=' ';
02036 outputRow[8]='\0';
02037 }
02038 }
02039
02040 static void
02041 writeString(FILE* fp, gzFile gzfp, const char* str)
02042 {
02043 if (fp) {
02044 fprintf(fp, "%s", str);
02045 }
02046 #ifdef COIN_USE_ZLIB
02047 if (gzfp) {
02048 gzprintf(gzfp, "%s", str);
02049 }
02050 #endif
02051 }
02052
02053
02054 static void outputCard(int formatType,int numberFields,
02055 FILE *fp, gzFile gzfp,
02056 std::string head, const char * name,
02057 const char outputValue[2][20],
02058 const char outputRow[2][100])
02059 {
02060
02061 std::string line = head;
02062 int i;
02063 if (!formatType) {
02064 char outputColumn[9];
02065 strcpy(outputColumn,name);
02066 for (i=0;i<8;i++) {
02067 if (outputColumn[i]=='\0')
02068 break;
02069 }
02070 for (;i<8;i++)
02071 outputColumn[i]=' ';
02072 outputColumn[8]='\0';
02073
02074 line += outputColumn;
02075 line += " ";
02076 for (i=0;i<numberFields;i++) {
02077
02078 line += outputRow[i];
02079 line += " ";
02080 line += outputValue[i];
02081 if (i<numberFields-1) {
02082
02083 line += " ";
02084 }
02085 }
02086 } else {
02087
02088 line += name;
02089 for (i=0;i<numberFields;i++) {
02090
02091 line += " ";
02092 line += outputRow[i];
02093 line += " ";
02094 line += outputValue[i];
02095 }
02096 }
02097
02098
02099 line += "\n";
02100 writeString(fp, gzfp, line.c_str());
02101 }
02102
02103 int
02104 CoinMpsIO::writeMps(const char *filename, int compression,
02105 int formatType, int numberAcross) const
02106 {
02107 std::string line = filename;
02108 FILE * fp = NULL;
02109 gzFile gzfp = NULL;
02110 switch (compression) {
02111 case 1:
02112 #ifdef COIN_USE_ZLIB
02113 {
02114 if (strcmp(line.c_str() +(line.size()-3), ".gz") != 0) {
02115 line += ".gz";
02116 }
02117 gzfp = gzopen(line.c_str(), "wb");
02118 if (gzfp) {
02119 break;
02120 }
02121 }
02122 #endif
02123 fp = fopen(filename,"w");
02124 if (!fp)
02125 return -1;
02126 break;
02127
02128 case 2:
02129 case 0:
02130 fp = fopen(filename,"w");
02131 if (!fp)
02132 return -1;
02133 break;
02134 }
02135
02136 const char * const * const rowNames = names_[0];
02137 const char * const * const columnNames = names_[1];
02138 int i;
02139 unsigned int length = 8;
02140 bool freeFormat = (formatType!=0);
02141 for (i = 0 ; i < numberRows_; ++i) {
02142 if (strlen(rowNames[i]) > length) {
02143 length = strlen(rowNames[i]);
02144 break;
02145 }
02146 }
02147 if (length <= 8) {
02148 for (i = 0 ; i < numberColumns_; ++i) {
02149 if (strlen(columnNames[i]) > length) {
02150 length = strlen(columnNames[i]);
02151 break;
02152 }
02153 }
02154 }
02155 if (length > 8 && !freeFormat) {
02156 freeFormat = true;
02157 formatType = 4;
02158 }
02159
02160
02161
02162 line = "NAME ";
02163 if (strcmp(problemName_,"")==0) {
02164 line.append("BLANK ");
02165 } else {
02166 if (strlen(problemName_) >= 8) {
02167 line.append(problemName_, 8);
02168 } else {
02169 line.append(problemName_);
02170 line.append(8-strlen(problemName_), ' ');
02171 }
02172 }
02173 if (freeFormat)
02174 line.append(" FREE");
02175
02176 line.append("\nROWS\n N OBJROW\n");
02177 writeString(fp, gzfp, line.c_str());
02178
02179
02180
02181
02182 char * sense = new char [numberRows_];
02183 memcpy( sense , getRowSense(), numberRows_);
02184 const double * rowLower = getRowLower();
02185 const double * rowUpper = getRowUpper();
02186
02187 for (i=0;i<numberRows_;i++) {
02188 line = " ";
02189 if (sense[i]!='R') {
02190 line.append(1,sense[i]);
02191 } else {
02192 if (rowLower[i]>-1.0e30) {
02193 if(rowUpper[i]<1.0e30) {
02194 line.append("L");
02195 } else {
02196 sense[i]='G';
02197 line.append(1,sense[i]);
02198 }
02199 } else {
02200 sense[i]='L';
02201 line.append(1,sense[i]);
02202 }
02203 }
02204 line.append(" ");
02205 line.append(rowNames[i]);
02206 line.append("\n");
02207 writeString(fp, gzfp, line.c_str());
02208 }
02209
02210
02211 writeString(fp, gzfp, "COLUMNS\n");
02212
02213 bool ifBounds=false;
02214 double largeValue = infinity_;
02215
02216 const double * columnLower = getColLower();
02217 const double * columnUpper = getColUpper();
02218 const double * objective = getObjCoefficients();
02219 const CoinPackedMatrix * matrix = getMatrixByCol();
02220 const double * elements = matrix->getElements();
02221 const int * rows = matrix->getIndices();
02222 const CoinBigIndex * starts = matrix->getVectorStarts();
02223 const int * lengths = matrix->getVectorLengths();
02224
02225 char outputValue[2][20];
02226 char outputRow[2][100];
02227
02228
02229 for (i=0;i<numberColumns_;i++) {
02230 if (objective[i]||lengths[i]) {
02231
02232 if (columnLower[i]||columnUpper[i]<largeValue||isInteger(i))
02233 ifBounds=true;
02234 int numberFields=0;
02235 if (objective[i]) {
02236 convertDouble(formatType,objective[i],outputValue[0],
02237 "OBJROW",outputRow[0]);
02238 numberFields=1;
02239 }
02240 if (numberFields==numberAcross) {
02241
02242 outputCard(formatType, numberFields,
02243 fp, gzfp, " ",
02244 columnNames[i],
02245 outputValue,
02246 outputRow);
02247 numberFields=0;
02248 }
02249 int j;
02250 for (j=0;j<lengths[i];j++) {
02251 convertDouble(formatType,elements[starts[i]+j],
02252 outputValue[numberFields],
02253 rowNames[rows[starts[i]+j]],
02254 outputRow[numberFields]);
02255 numberFields++;
02256 if (numberFields==numberAcross) {
02257
02258 outputCard(formatType, numberFields,
02259 fp, gzfp, " ",
02260 columnNames[i],
02261 outputValue,
02262 outputRow);
02263 numberFields=0;
02264 }
02265 }
02266 if (numberFields) {
02267
02268 outputCard(formatType, numberFields,
02269 fp, gzfp, " ",
02270 columnNames[i],
02271 outputValue,
02272 outputRow);
02273 }
02274 }
02275 }
02276
02277 bool ifRange=false;
02278
02279 writeString(fp, gzfp, "RHS\n");
02280
02281 int numberFields = 0;
02282 for (i=0;i<numberRows_;i++) {
02283 double value;
02284 switch (sense[i]) {
02285 case 'E':
02286 value=rowLower[i];
02287 break;
02288 case 'R':
02289 value=rowUpper[i];
02290 ifRange=true;
02291 break;
02292 case 'L':
02293 value=rowUpper[i];
02294 break;
02295 case 'G':
02296 value=rowLower[i];
02297 break;
02298 default:
02299 value=0.0;
02300 break;
02301 }
02302 if (value != 0.0) {
02303 convertDouble(formatType,value,
02304 outputValue[numberFields],
02305 rowNames[i],
02306 outputRow[numberFields]);
02307 numberFields++;
02308 if (numberFields==numberAcross) {
02309
02310 outputCard(formatType, numberFields,
02311 fp, gzfp, " ",
02312 "RHS",
02313 outputValue,
02314 outputRow);
02315 numberFields=0;
02316 }
02317 }
02318 }
02319 if (numberFields) {
02320
02321 outputCard(formatType, numberFields,
02322 fp, gzfp, " ",
02323 "RHS",
02324 outputValue,
02325 outputRow);
02326 }
02327
02328 if (ifRange) {
02329
02330 writeString(fp, gzfp, "RANGES\n");
02331
02332 numberFields = 0;
02333 for (i=0;i<numberRows_;i++) {
02334 if (sense[i]=='R') {
02335 double value =rowUpper[i]-rowLower[i];
02336 if (value<1.0e30) {
02337 convertDouble(formatType,value,
02338 outputValue[numberFields],
02339 rowNames[i],
02340 outputRow[numberFields]);
02341 numberFields++;
02342 if (numberFields==numberAcross) {
02343
02344 outputCard(formatType, numberFields,
02345 fp, gzfp, " ",
02346 "RANGE",
02347 outputValue,
02348 outputRow);
02349 numberFields=0;
02350 }
02351 }
02352 }
02353 }
02354 if (numberFields) {
02355
02356 outputCard(formatType, numberFields,
02357 fp, gzfp, " ",
02358 "RANGE",
02359 outputValue,
02360 outputRow);
02361 }
02362 }
02363 delete [] sense;
02364 if (ifBounds) {
02365
02366 writeString(fp, gzfp, "BOUNDS\n");
02367
02368 for (i=0;i<numberColumns_;i++) {
02369 if (objective[i]||lengths[i]) {
02370
02371 if (columnLower[i]||columnUpper[i]<largeValue||isInteger(i)) {
02372 double lowerValue = columnLower[i];
02373 double upperValue = columnUpper[i];
02374 if (isInteger(i)) {
02375
02376 lowerValue = max(lowerValue,(double) -INT_MAX);
02377 upperValue = min(upperValue,(double) INT_MAX);
02378 }
02379 int numberFields=1;
02380 std::string header[2];
02381 double value[2];
02382 if (lowerValue<=-largeValue) {
02383
02384 if (upperValue>=largeValue) {
02385 header[0]=" FR ";
02386 value[0] = largeValue;
02387 } else {
02388 header[0]=" MI ";
02389 value[0] = largeValue;
02390 header[1]=" UP ";
02391 value[1] = upperValue;
02392 numberFields=2;
02393 }
02394 } else if (fabs(upperValue-lowerValue)<1.0e-8) {
02395 header[0]=" FX ";
02396 value[0] = lowerValue;
02397 } else {
02398
02399 if (lowerValue) {
02400
02401 header[0]=" LO ";
02402 value[0] = lowerValue;
02403 if (isInteger(i)) {
02404
02405 header[1]=" UI ";
02406 value[1] = upperValue;
02407 numberFields=2;
02408 } else if (upperValue<largeValue) {
02409
02410 header[1]=" UP ";
02411 value[1] = upperValue;
02412 numberFields=2;
02413 }
02414 } else {
02415 if (isInteger(i)) {
02416
02417 if (fabs(upperValue-1.0)<1.0e-8) {
02418
02419 header[0]=" BV ";
02420 value[0] = largeValue;
02421 } else {
02422
02423 header[0]=" UI ";
02424 value[0] = upperValue;
02425 }
02426 } else {
02427
02428 header[0]=" UP ";
02429 value[0] = upperValue;
02430 }
02431 }
02432 }
02433
02434 int j;
02435 for (j=0;j<numberFields;j++) {
02436 convertDouble(formatType,value[j],
02437 outputValue[0],
02438 columnNames[i],
02439 outputRow[0]);
02440
02441 outputCard(formatType, 1,
02442 fp, gzfp, header[j],
02443 "BOUND",
02444 outputValue,
02445 outputRow);
02446 }
02447 }
02448 }
02449 }
02450 }
02451
02452
02453
02454 writeString(fp, gzfp, "ENDATA\n");
02455
02456 if (fp) {
02457 fclose(fp);
02458 }
02459 #ifdef COIN_USE_ZLIB
02460 if (gzfp) {
02461 gzclose(gzfp);
02462 }
02463 #endif
02464
02465 return 0;
02466 }
02467
02468
02469
02470 const char * CoinMpsIO::getProblemName() const
02471 {
02472 return problemName_;
02473 }
02474
02475 const char * CoinMpsIO::getObjectiveName() const
02476 {
02477 return objectiveName_;
02478 }
02479
02480 const char * CoinMpsIO::getRhsName() const
02481 {
02482 return rhsName_;
02483 }
02484
02485 const char * CoinMpsIO::getRangeName() const
02486 {
02487 return rangeName_;
02488 }
02489
02490 const char * CoinMpsIO::getBoundName() const
02491 {
02492 return boundName_;
02493 }
02494
02495
02496
02497
02498 int CoinMpsIO::getNumCols() const
02499 {
02500 return numberColumns_;
02501 }
02502 int CoinMpsIO::getNumRows() const
02503 {
02504 return numberRows_;
02505 }
02506 int CoinMpsIO::getNumElements() const
02507 {
02508 return numberElements_;
02509 }
02510
02511
02512
02513
02514 const double * CoinMpsIO::getColLower() const
02515 {
02516 return collower_;
02517 }
02518 const double * CoinMpsIO::getColUpper() const
02519 {
02520 return colupper_;
02521 }
02522
02523
02524
02525
02526 const double * CoinMpsIO::getRowLower() const
02527 {
02528 return rowlower_;
02529 }
02530 const double * CoinMpsIO::getRowUpper() const
02531 {
02532 return rowupper_;
02533 }
02534
02537 inline void
02538 CoinMpsIO::convertBoundToSense(const double lower, const double upper,
02539 char& sense, double& right,
02540 double& range) const
02541 {
02542 range = 0.0;
02543 if (lower > -infinity_) {
02544 if (upper < infinity_) {
02545 right = upper;
02546 if (upper==lower) {
02547 sense = 'E';
02548 } else {
02549 sense = 'R';
02550 range = upper - lower;
02551 }
02552 } else {
02553 sense = 'G';
02554 right = lower;
02555 }
02556 } else {
02557 if (upper < infinity_) {
02558 sense = 'L';
02559 right = upper;
02560 } else {
02561 sense = 'N';
02562 right = 0.0;
02563 }
02564 }
02565 }
02566
02567
02570 inline void
02571 CoinMpsIO::convertSenseToBound(const char sense, const double right,
02572 const double range,
02573 double& lower, double& upper) const
02574 {
02575 switch (sense) {
02576 case 'E':
02577 lower = upper = right;
02578 break;
02579 case 'L':
02580 lower = -infinity_;
02581 upper = right;
02582 break;
02583 case 'G':
02584 lower = right;
02585 upper = infinity_;
02586 break;
02587 case 'R':
02588 lower = right - range;
02589 upper = right;
02590 break;
02591 case 'N':
02592 lower = -infinity_;
02593 upper = infinity_;
02594 break;
02595 }
02596 }
02597
02598
02599
02600 const char * CoinMpsIO::getRowSense() const
02601 {
02602 if ( rowsense_==NULL ) {
02603
02604 int nr=numberRows_;
02605 rowsense_ = (char *) malloc(nr*sizeof(char));
02606
02607
02608 double dum1,dum2;
02609 int i;
02610 for ( i=0; i<nr; i++ ) {
02611 convertBoundToSense(rowlower_[i],rowupper_[i],rowsense_[i],dum1,dum2);
02612 }
02613 }
02614 return rowsense_;
02615 }
02616
02617
02618
02619
02620 const double * CoinMpsIO::getRightHandSide() const
02621 {
02622 if ( rhs_==NULL ) {
02623
02624 int nr=numberRows_;
02625 rhs_ = (double *) malloc(nr*sizeof(double));
02626
02627
02628 char dum1;
02629 double dum2;
02630 int i;
02631 for ( i=0; i<nr; i++ ) {
02632 convertBoundToSense(rowlower_[i],rowupper_[i],dum1,rhs_[i],dum2);
02633 }
02634 }
02635 return rhs_;
02636 }
02637
02638
02639
02640
02641
02642 const double * CoinMpsIO::getRowRange() const
02643 {
02644 if ( rowrange_==NULL ) {
02645
02646 int nr=numberRows_;
02647 rowrange_ = (double *) malloc(nr*sizeof(double));
02648 std::fill(rowrange_,rowrange_+nr,0.0);
02649
02650 char dum1;
02651 double dum2;
02652 int i;
02653 for ( i=0; i<nr; i++ ) {
02654 convertBoundToSense(rowlower_[i],rowupper_[i],dum1,dum2,rowrange_[i]);
02655 }
02656 }
02657 return rowrange_;
02658 }
02659
02660 const double * CoinMpsIO::getObjCoefficients() const
02661 {
02662 return objective_;
02663 }
02664
02665
02666
02667
02668 const CoinPackedMatrix * CoinMpsIO::getMatrixByRow() const
02669 {
02670 if ( matrixByRow_ == NULL && matrixByColumn_) {
02671 matrixByRow_ = new CoinPackedMatrix(*matrixByColumn_);
02672 matrixByRow_->reverseOrdering();
02673 }
02674 return matrixByRow_;
02675 }
02676
02677
02678
02679
02680 const CoinPackedMatrix * CoinMpsIO::getMatrixByCol() const
02681 {
02682 return matrixByColumn_;
02683 }
02684
02685
02686
02687
02688 void
02689 CoinMpsIO::setMpsDataWithoutRowAndColNames(
02690 const CoinPackedMatrix& m, const double infinity,
02691 const double* collb, const double* colub,
02692 const double* obj, const char* integrality,
02693 const double* rowlb, const double* rowub)
02694 {
02695 freeAll();
02696 if (m.isColOrdered()) {
02697 matrixByColumn_ = new CoinPackedMatrix(m);
02698 } else {
02699 matrixByColumn_ = new CoinPackedMatrix;
02700 matrixByColumn_->reverseOrderedCopyOf(m);
02701 }
02702 numberColumns_ = matrixByColumn_->getNumCols();
02703 numberRows_ = matrixByColumn_->getNumRows();
02704 numberElements_ = matrixByColumn_->getNumElements();
02705 defaultBound_ = 1;
02706 infinity_ = infinity;
02707 objectiveOffset_ = 0;
02708
02709 rowlower_ = (double *) malloc (numberRows_ * sizeof(double));
02710 rowupper_ = (double *) malloc (numberRows_ * sizeof(double));
02711 collower_ = (double *) malloc (numberColumns_ * sizeof(double));
02712 colupper_ = (double *) malloc (numberColumns_ * sizeof(double));
02713 objective_ = (double *) malloc (numberColumns_ * sizeof(double));
02714 std::copy(rowlb, rowlb + numberRows_, rowlower_);
02715 std::copy(rowub, rowub + numberRows_, rowupper_);
02716 std::copy(collb, collb + numberColumns_, collower_);
02717 std::copy(colub, colub + numberColumns_, colupper_);
02718 std::copy(obj, obj + numberColumns_, objective_);
02719 if (integrality) {
02720 integerType_ = (char *) malloc (numberColumns_ * sizeof(char));
02721 std::copy(integrality, integrality + numberColumns_, integerType_);
02722 } else {
02723 integerType_ = 0;
02724 }
02725
02726 problemName_ = strdup("");
02727 objectiveName_ = strdup("");
02728 rhsName_ = strdup("");
02729 rangeName_ = strdup("");
02730 boundName_ = strdup("");
02731 }
02732
02733
02734 void
02735 CoinMpsIO::setMpsDataColAndRowNames(
02736 char const * const * const colnames,
02737 char const * const * const rownames)
02738 {
02739 releaseRowNames();
02740 releaseColumnNames();
02741
02742 names_[0] = (char **) malloc(numberRows_ * sizeof(char *));
02743 names_[1] = (char **) malloc (numberColumns_ * sizeof(char *));
02744 numberHash_[0]=numberRows_;
02745 numberHash_[1]=numberColumns_;
02746 char** rowNames_ = names_[0];
02747 char** colNames_ = names_[1];
02748 int i;
02749 if (rownames) {
02750 for (i = 0 ; i < numberRows_; ++i) {
02751 rowNames_[i] = strdup(rownames[i]);
02752 }
02753 } else {
02754 for (i = 0; i < numberRows_; ++i) {
02755 rowNames_[i] = (char *) malloc (9 * sizeof(char));
02756 sprintf(rowNames_[i],"R%7.7d",i);
02757 }
02758 }
02759 if (colnames) {
02760 for (i = 0 ; i < numberColumns_; ++i) {
02761 colNames_[i] = strdup(colnames[i]);
02762 }
02763 } else {
02764 for (i = 0; i < numberColumns_; ++i) {
02765 colNames_[i] = (char *) malloc (9 * sizeof(char));
02766 sprintf(colNames_[i],"C%7.7d",i);
02767 }
02768 }
02769 }
02770
02771 void
02772 CoinMpsIO::setMpsDataColAndRowNames(
02773 const std::vector<std::string> & colnames,
02774 const std::vector<std::string> & rownames)
02775 {
02776
02777 names_[0] = (char **) malloc(numberRows_ * sizeof(char *));
02778 names_[1] = (char **) malloc (numberColumns_ * sizeof(char *));
02779 char** rowNames_ = names_[0];
02780 char** colNames_ = names_[1];
02781 int i;
02782 if (rownames.size()!=0) {
02783 for (i = 0 ; i < numberRows_; ++i) {
02784 rowNames_[i] = strdup(rownames[i].c_str());
02785 }
02786 } else {
02787 for (i = 0; i < numberRows_; ++i) {
02788 rowNames_[i] = (char *) malloc (9 * sizeof(char));
02789 sprintf(rowNames_[i],"R%7.7d",i);
02790 }
02791 }
02792 if (colnames.size()!=0) {
02793 for (i = 0 ; i < numberColumns_; ++i) {
02794 colNames_[i] = strdup(colnames[i].c_str());
02795 }
02796 } else {
02797 for (i = 0; i < numberColumns_; ++i) {
02798 colNames_[i] = (char *) malloc (9 * sizeof(char));
02799 sprintf(colNames_[i],"C%7.7d",i);
02800 }
02801 }
02802 }
02803
02804 void
02805 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02806 const double* collb, const double* colub,
02807 const double* obj, const char* integrality,
02808 const double* rowlb, const double* rowub,
02809 char const * const * const colnames,
02810 char const * const * const rownames)
02811 {
02812 setMpsDataWithoutRowAndColNames(m,infinity,collb,colub,obj,integrality,rowlb,rowub);
02813 setMpsDataColAndRowNames(colnames,rownames);
02814 }
02815
02816 void
02817 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02818 const double* collb, const double* colub,
02819 const double* obj, const char* integrality,
02820 const double* rowlb, const double* rowub,
02821 const std::vector<std::string> & colnames,
02822 const std::vector<std::string> & rownames)
02823 {
02824 setMpsDataWithoutRowAndColNames(m,infinity,collb,colub,obj,integrality,rowlb,rowub);
02825 setMpsDataColAndRowNames(colnames,rownames);
02826 }
02827
02828 void
02829 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02830 const double* collb, const double* colub,
02831 const double* obj, const char* integrality,
02832 const char* rowsen, const double* rowrhs,
02833 const double* rowrng,
02834 char const * const * const colnames,
02835 char const * const * const rownames)
02836 {
02837 const int numrows = matrixByColumn_->getNumRows();
02838
02839 double * rlb = numrows ? new double[numrows] : 0;
02840 double * rub = numrows ? new double[numrows] : 0;
02841
02842 for (int i = 0; i < numrows; ++i) {
02843 convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]);
02844 }
02845 setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub,
02846 colnames, rownames);
02847 }
02848
02849 void
02850 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02851 const double* collb, const double* colub,
02852 const double* obj, const char* integrality,
02853 const char* rowsen, const double* rowrhs,
02854 const double* rowrng,
02855 const std::vector<std::string> & colnames,
02856 const std::vector<std::string> & rownames)
02857 {
02858 const int numrows = matrixByColumn_->getNumRows();
02859
02860 double * rlb = numrows ? new double[numrows] : 0;
02861 double * rub = numrows ? new double[numrows] : 0;
02862
02863 for (int i = 0; i < numrows; ++i) {
02864 convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]);
02865 }
02866 setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub,
02867 colnames, rownames);
02868 }
02869
02870
02871
02872
02873
02874 bool CoinMpsIO::isContinuous(int columnNumber) const
02875 {
02876 const char * intType = integerType_;
02877 if ( intType==NULL ) return true;
02878 assert (columnNumber>=0 && columnNumber < numberColumns_);
02879 if ( intType[columnNumber]==0 ) return true;
02880 return false;
02881 }
02882
02883
02884
02885
02886
02887 bool CoinMpsIO::isInteger(int columnNumber) const
02888 {
02889 const char * intType = integerType_;
02890 if ( intType==NULL ) return false;
02891 assert (columnNumber>=0 && columnNumber < numberColumns_);
02892 if ( intType[columnNumber]!=0 ) return true;
02893 return false;
02894 }
02895
02896 const char * CoinMpsIO::integerColumns() const
02897 {
02898 return integerType_;
02899 }
02900
02901 void
02902 CoinMpsIO::copyInIntegerInformation(const char * integerType)
02903 {
02904 if (integerType) {
02905 if (!integerType_)
02906 integerType_ = new char [numberColumns_];
02907 memcpy(integerType_,integerType,numberColumns_);
02908 } else {
02909 delete [] integerType_;
02910 integerType_=NULL;
02911 }
02912 }
02913
02914 const char * CoinMpsIO::rowName(int index) const
02915 {
02916 if (index>=0&&index<numberRows_) {
02917 return names_[0][index];
02918 } else {
02919 return NULL;
02920 }
02921 }
02922 const char * CoinMpsIO::columnName(int index) const
02923 {
02924 if (index>=0&&index<numberColumns_) {
02925 return names_[1][index];
02926 } else {
02927 return NULL;
02928 }
02929 }
02930
02931 int CoinMpsIO::rowIndex(const char * name) const
02932 {
02933 if (!hash_[0]) {
02934 if (numberRows_) {
02935 startHash(0);
02936 } else {
02937 return -1;
02938 }
02939 }
02940 return findHash ( name , 0 );
02941 }
02942 int CoinMpsIO::columnIndex(const char * name) const
02943 {
02944 if (!hash_[1]) {
02945 if (numberColumns_) {
02946 startHash(1);
02947 } else {
02948 return -1;
02949 }
02950 }
02951 return findHash ( name , 1 );
02952 }
02953
02954
02955 void CoinMpsIO::releaseRowInformation()
02956 {
02957 free(rowlower_);
02958 free(rowupper_);
02959 rowlower_=NULL;
02960 rowupper_=NULL;
02961 }
02962
02963 void CoinMpsIO::releaseColumnInformation()
02964 {
02965 free(collower_);
02966 free(colupper_);
02967 free(objective_);
02968 collower_=NULL;
02969 colupper_=NULL;
02970 objective_=NULL;
02971 }
02972
02973 void CoinMpsIO::releaseIntegerInformation()
02974 {
02975 free(integerType_);
02976 integerType_=NULL;
02977 }
02978
02979 void CoinMpsIO::releaseRowNames()
02980 {
02981 releaseRedundantInformation();
02982 int i;
02983 for (i=0;i<numberHash_[0];i++) {
02984 free(names_[0][i]);
02985 }
02986 free(names_[0]);
02987 names_[0]=NULL;
02988 numberHash_[0]=0;
02989 }
02990
02991 void CoinMpsIO::releaseColumnNames()
02992 {
02993 releaseRedundantInformation();
02994 int i;
02995 for (i=0;i<numberHash_[1];i++) {
02996 free(names_[1][i]);
02997 }
02998 free(names_[1]);
02999 names_[1]=NULL;
03000 numberHash_[1]=0;
03001 }
03002
03003 void CoinMpsIO::releaseMatrixInformation()
03004 {
03005 releaseRedundantInformation();
03006 delete matrixByColumn_;
03007 matrixByColumn_=NULL;
03008 }
03009
03010
03011
03012
03013
03014
03015 CoinMpsIO::CoinMpsIO ()
03016 :
03017 problemName_(strdup("")),
03018 objectiveName_(strdup("")),
03019 rhsName_(strdup("")),
03020 rangeName_(strdup("")),
03021 boundName_(strdup("")),
03022 numberRows_(0),
03023 numberColumns_(0),
03024 numberElements_(0),
03025 rowsense_(NULL),
03026 rhs_(NULL),
03027 rowrange_(NULL),
03028 matrixByRow_(NULL),
03029 matrixByColumn_(NULL),
03030 rowlower_(NULL),
03031 rowupper_(NULL),
03032 collower_(NULL),
03033 colupper_(NULL),
03034 objective_(NULL),
03035 objectiveOffset_(0.0),
03036 integerType_(NULL),
03037 fileName_(strdup("stdin")),
03038 defaultBound_(1),
03039 infinity_(COIN_DBL_MAX),
03040 defaultHandler_(true),
03041 cardReader_(NULL)
03042 {
03043 numberHash_[0]=0;
03044 hash_[0]=NULL;
03045 names_[0]=NULL;
03046 numberHash_[1]=0;
03047 hash_[1]=NULL;
03048 names_[1]=NULL;
03049 handler_ = new CoinMessageHandler();
03050 messages_ = CoinMessage();
03051 }
03052
03053
03054
03055
03056 CoinMpsIO::CoinMpsIO(const CoinMpsIO & rhs)
03057 :
03058 problemName_(strdup("")),
03059 objectiveName_(strdup("")),
03060 rhsName_(strdup("")),
03061 rangeName_(strdup("")),
03062 boundName_(strdup("")),
03063 numberRows_(0),
03064 numberColumns_(0),
03065 numberElements_(0),
03066 rowsense_(NULL),
03067 rhs_(NULL),
03068 rowrange_(NULL),
03069 matrixByRow_(NULL),
03070 matrixByColumn_(NULL),
03071 rowlower_(NULL),
03072 rowupper_(NULL),
03073 collower_(NULL),
03074 colupper_(NULL),
03075 objective_(NULL),
03076 objectiveOffset_(0.0),
03077 integerType_(NULL),
03078 fileName_(strdup("stdin")),
03079 defaultBound_(1),
03080 infinity_(COIN_DBL_MAX),
03081 defaultHandler_(true),
03082 cardReader_(NULL)
03083 {
03084 numberHash_[0]=0;
03085 hash_[0]=NULL;
03086 names_[0]=NULL;
03087 numberHash_[1]=0;
03088 hash_[1]=NULL;
03089 names_[1]=NULL;
03090 if ( rhs.rowlower_ !=NULL || rhs.collower_ != NULL) {
03091 gutsOfCopy(rhs);
03092
03093
03094
03095 }
03096 defaultHandler_ = rhs.defaultHandler_;
03097 if (defaultHandler_)
03098 handler_ = new CoinMessageHandler(*rhs.handler_);
03099 else
03100 handler_ = rhs.handler_;
03101 messages_ = CoinMessage();
03102 }
03103
03104 void CoinMpsIO::gutsOfCopy(const CoinMpsIO & rhs)
03105 {
03106 defaultHandler_ = rhs.defaultHandler_;
03107 if (rhs.matrixByColumn_)
03108 matrixByColumn_=new CoinPackedMatrix(*(rhs.matrixByColumn_));
03109 numberElements_=rhs.numberElements_;
03110 numberRows_=rhs.numberRows_;
03111 numberColumns_=rhs.numberColumns_;
03112 if (rhs.rowlower_) {
03113 rowlower_ = (double *) malloc(numberRows_*sizeof(double));
03114 rowupper_ = (double *) malloc(numberRows_*sizeof(double));
03115 memcpy(rowlower_,rhs.rowlower_,numberRows_*sizeof(double));
03116 memcpy(rowupper_,rhs.rowupper_,numberRows_*sizeof(double));
03117 }
03118 if (rhs.collower_) {
03119 collower_ = (double *) malloc(numberColumns_*sizeof(double));
03120 colupper_ = (double *) malloc(numberColumns_*sizeof(double));
03121 objective_ = (double *) malloc(numberColumns_*sizeof(double));
03122 memcpy(collower_,rhs.collower_,numberColumns_*sizeof(double));
03123 memcpy(colupper_,rhs.colupper_,numberColumns_*sizeof(double));
03124 memcpy(objective_,rhs.objective_,numberColumns_*sizeof(double));
03125 }
03126 if (rhs.integerType_) {
03127 integerType_ = (char *) malloc (numberColumns_*sizeof(char));
03128 memcpy(integerType_,rhs.integerType_,numberColumns_*sizeof(char));
03129 }
03130 free(fileName_);
03131 free(problemName_);
03132 free(objectiveName_);
03133 free(rhsName_);
03134 free(rangeName_);
03135 free(boundName_);
03136 fileName_ = strdup(rhs.fileName_);
03137 problemName_ = strdup(rhs.problemName_);
03138 objectiveName_ = strdup(rhs.objectiveName_);
03139 rhsName_ = strdup(rhs.rhsName_);
03140 rangeName_ = strdup(rhs.rangeName_);
03141 boundName_ = strdup(rhs.boundName_);
03142 numberHash_[0]=rhs.numberHash_[0];
03143 numberHash_[1]=rhs.numberHash_[1];
03144 defaultBound_=rhs.defaultBound_;
03145 infinity_=rhs.infinity_;
03146 objectiveOffset_=rhs.objectiveOffset_;
03147 int section;
03148 for (section=0;section<2;section++) {
03149 if (numberHash_[section]) {
03150 char ** names2 = rhs.names_[section];
03151 names_[section] = (char **) malloc(numberHash_[section]*
03152 sizeof(char *));
03153 char ** names = names_[section];
03154 int i;
03155 for (i=0;i<numberHash_[section];i++) {
03156 names[i]=strdup(names2[i]);
03157 }
03158 }
03159 }
03160 }
03161
03162
03163
03164
03165 CoinMpsIO::~CoinMpsIO ()
03166 {
03167 gutsOfDestructor();
03168 }
03169
03170
03171
03172
03173 CoinMpsIO &
03174 CoinMpsIO::operator=(const CoinMpsIO& rhs)
03175 {
03176 if (this != &rhs) {
03177 gutsOfDestructor();
03178 if ( rhs.rowlower_ !=NULL || rhs.collower_ != NULL) {
03179 gutsOfCopy(rhs);
03180 }
03181 defaultHandler_ = rhs.defaultHandler_;
03182 if (defaultHandler_)
03183 handler_ = new CoinMessageHandler(*rhs.handler_);
03184 else
03185 handler_ = rhs.handler_;
03186 messages_ = CoinMessage();
03187 }
03188 return *this;
03189 }
03190
03191
03192 void CoinMpsIO::gutsOfDestructor()
03193 {
03194 freeAll();
03195 if (defaultHandler_) {
03196 delete handler_;
03197 handler_ = NULL;
03198 }
03199 delete cardReader_;
03200 cardReader_ = NULL;
03201 }
03202
03203
03204 void CoinMpsIO::freeAll()
03205 {
03206 releaseRedundantInformation();
03207 releaseRowNames();
03208 releaseColumnNames();
03209 delete matrixByRow_;
03210 delete matrixByColumn_;
03211 matrixByRow_=NULL;
03212 matrixByColumn_=NULL;
03213 free(rowlower_);
03214 free(rowupper_);
03215 free(collower_);
03216 free(colupper_);
03217 free(objective_);
03218 free(integerType_);
03219 free(fileName_);
03220 rowlower_=NULL;
03221 rowupper_=NULL;
03222 collower_=NULL;
03223 colupper_=NULL;
03224 objective_=NULL;
03225 integerType_=NULL;
03226 fileName_=NULL;
03227 free(problemName_);
03228 free(objectiveName_);
03229 free(rhsName_);
03230 free(rangeName_);
03231 free(boundName_);
03232 problemName_=NULL;
03233 objectiveName_=NULL;
03234 rhsName_=NULL;
03235 rangeName_=NULL;
03236 boundName_=NULL;
03237 }
03238
03239
03240
03241 void CoinMpsIO::releaseRedundantInformation()
03242 {
03243 free( rowsense_);
03244 free( rhs_);
03245 free( rowrange_);
03246 rowsense_=NULL;
03247 rhs_=NULL;
03248 rowrange_=NULL;
03249 free (hash_[0]);
03250 free (hash_[1]);
03251 hash_[0]=0;
03252 hash_[1]=0;
03253 delete matrixByRow_;
03254 matrixByRow_=NULL;
03255 }
03256
03257 void
03258 CoinMpsIO::passInMessageHandler(CoinMessageHandler * handler)
03259 {
03260 if (defaultHandler_)
03261 delete handler_;
03262 defaultHandler_=false;
03263 handler_=handler;
03264 }
03265
03266 void
03267 CoinMpsIO::newLanguage(CoinMessages::Language language)
03268 {
03269 messages_ = CoinMessage(language);
03270 }
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281 int
03282 CoinMpsIO::readQuadraticMps(const char * filename,
03283 int * &columnStart, int * &column2, double * &elements,
03284 int checkSymmetry)
03285 {
03286
03287 FILE *fp=NULL;
03288 gzFile gzfp=NULL;
03289 int returnCode = dealWithFileName(filename,"",fp,gzfp);
03290 if (returnCode<0) {
03291 return -1;
03292 } else if (returnCode>0) {
03293 delete cardReader_;
03294 cardReader_ = new CoinMpsCardReader ( fp , gzfp, this);
03295 }
03296
03297 cardReader_->readToNextSection();
03298
03299
03300 if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION )
03301 cardReader_->readToNextSection();
03302 if ( cardReader_->whichSection ( ) == COIN_QUADRATIC_SECTION ) {
03303
03304 free(problemName_);
03305 problemName_=strdup(cardReader_->columnName());
03306 } else if ( cardReader_->whichSection ( ) == COIN_EOF_SECTION ) {
03307 handler_->message(COIN_MPS_EOF,messages_)<<fileName_
03308 <<CoinMessageEol;
03309 return -3;
03310 } else {
03311 handler_->message(COIN_MPS_BADFILE1,messages_)<<cardReader_->card()
03312 <<cardReader_->cardNumber()
03313 <<fileName_
03314 <<CoinMessageEol;
03315 return -2;
03316 }
03317
03318 int numberErrors = 0;
03319
03320
03321 int maximumNonZeros = 5 *numberColumns_;
03322
03323 int * column = (int *) malloc(maximumNonZeros*sizeof(int));
03324 int * column2Temp = (int *) malloc(maximumNonZeros*sizeof(int));
03325 double * elementTemp = (double *) malloc(maximumNonZeros*sizeof(double));
03326
03327 startHash(1);
03328 int numberElements=0;
03329
03330 const double tinyElement = 1.0e-14;
03331
03332 while ( cardReader_->nextField ( ) == COIN_QUADRATIC_SECTION ) {
03333 switch ( cardReader_->mpsType ( ) ) {
03334 case COIN_BLANK_COLUMN:
03335 if ( fabs ( cardReader_->value ( ) ) > tinyElement ) {
03336 if ( numberElements == maximumNonZeros ) {
03337 maximumNonZeros = ( 3 * maximumNonZeros ) / 2 + 1000;
03338 column = ( COINColumnIndex * )
03339 realloc ( column, maximumNonZeros * sizeof ( COINColumnIndex ) );
03340 column2Temp = ( COINColumnIndex * )
03341 realloc ( column2Temp, maximumNonZeros * sizeof ( COINColumnIndex ) );
03342 elementTemp = ( double * )
03343 realloc ( elementTemp, maximumNonZeros * sizeof ( double ) );
03344 }
03345
03346 COINColumnIndex iColumn1 = findHash ( cardReader_->columnName ( ) , 1 );
03347 COINColumnIndex iColumn2 = findHash ( cardReader_->rowName ( ) , 1 );
03348
03349 if ( iColumn1 >= 0 ) {
03350 if (iColumn2 >=0) {
03351 double value = cardReader_->value ( );
03352 column[numberElements]=iColumn1;
03353 column2Temp[numberElements]=iColumn2;
03354 elementTemp[numberElements++]=value;
03355 } else {
03356 numberErrors++;
03357 if ( numberErrors < 100 ) {
03358 handler_->message(COIN_MPS_NOMATCHROW,messages_)
03359 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
03360 <<CoinMessageEol;
03361 } else if (numberErrors > 100000) {
03362 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03363 return numberErrors;
03364 }
03365 }
03366 } else {
03367 numberErrors++;
03368 if ( numberErrors < 100 ) {
03369 handler_->message(COIN_MPS_NOMATCHCOL,messages_)
03370 <<cardReader_->columnName()<<cardReader_->cardNumber()<<cardReader_->card()
03371 <<CoinMessageEol;
03372 } else if (numberErrors > 100000) {
03373 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03374 return numberErrors;
03375 }
03376 }
03377 }
03378 break;
03379 default:
03380 numberErrors++;
03381 if ( numberErrors < 100 ) {
03382 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
03383 <<cardReader_->card()
03384 <<CoinMessageEol;
03385 } else if (numberErrors > 100000) {
03386 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03387 return numberErrors;
03388 }
03389 }
03390 }
03391 stopHash(1);
03392
03393 columnStart = new int [numberColumns_+1];
03394
03395 int * count = new int[numberColumns_];
03396 memset(count,0,numberColumns_*sizeof(int));
03397 CoinBigIndex i;
03398
03399 if (checkSymmetry&&numberErrors)
03400 checkSymmetry=2;
03401 if (checkSymmetry) {
03402 if (checkSymmetry==1) {
03403
03404 for ( i = 0; i < numberElements; i++ ) {
03405 int iColumn = column[i];
03406 int iColumn2 = column2Temp[i];
03407 if (iColumn2<iColumn) {
03408 numberErrors=-4;
03409 column[i]=iColumn2;
03410 column2Temp[i]=iColumn;
03411 }
03412 }
03413 } else {
03414
03415 for ( i = 0; i < numberElements; i++ ) {
03416 int iColumn = column[i];
03417 int iColumn2 = column2Temp[i];
03418 if (iColumn2<iColumn) {
03419 column[i]=iColumn2;
03420 column2Temp[i]=iColumn;
03421 }
03422 }
03423 }
03424 }
03425 for ( i = 0; i < numberElements; i++ ) {
03426 int iColumn = column[i];
03427 count[iColumn]++;
03428 }
03429
03430 int number = 0;
03431 columnStart[0]=0;
03432 for (i=0;i<numberColumns_;i++) {
03433 number += count[i];
03434 count[i]= columnStart[i];
03435 columnStart[i+1]=number;
03436 }
03437 column2 = new int[numberElements];
03438 elements = new double[numberElements];
03439
03440
03441 for ( i = 0; i < numberElements; i++ ) {
03442 int iColumn = column[i];
03443 int iColumn2 = column2Temp[i];
03444 int put = count[iColumn];
03445 elements[put]=elementTemp[i];
03446 column2[put++]=iColumn2;
03447 count[iColumn]=put;
03448 }
03449 free(column);
03450 free(column2Temp);
03451 free(elementTemp);
03452
03453
03454 for (i=0;i<numberColumns_;i++)
03455 count[i] = -1;
03456
03457 int start = 0;
03458 number=0;
03459 for (i=0;i<numberColumns_;i++) {
03460 int j;
03461 for (j=start;j<columnStart[i+1];j++) {
03462 int iColumn2 = column2[j];
03463 if (count[iColumn2]<0) {
03464 count[iColumn2]=j;
03465 } else {
03466
03467 int iOther = count[iColumn2];
03468 double value = elements[iOther]+elements[j];
03469 elements[iOther]=value;
03470 elements[j]=0.0;
03471 }
03472 }
03473 for (j=start;j<columnStart[i+1];j++) {
03474 int iColumn2 = column2[j];
03475 count[iColumn2]=-1;
03476 double value = elements[j];
03477 if (value) {
03478 column2[number]=iColumn2;
03479 elements[number++]=value;
03480 }
03481 }
03482 start = columnStart[i+1];
03483 columnStart[i+1]=number;
03484 }
03485
03486 delete [] count;
03487 return numberErrors;
03488 }
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502 int
03503 CoinMpsIO::readConicMps(const char * filename,
03504 int * &columnStart, int * &column, int & numberCones)
03505 {
03506
03507 FILE *fp=NULL;
03508 gzFile gzfp=NULL;
03509 int returnCode = dealWithFileName(filename,"",fp,gzfp);
03510 if (returnCode<0) {
03511 return -1;
03512 } else if (returnCode>0) {
03513 delete cardReader_;
03514 cardReader_ = new CoinMpsCardReader ( fp , gzfp, this);
03515 }
03516
03517 cardReader_->readToNextSection();
03518
03519
03520 if ( cardReader_->whichSection ( ) == COIN_NAME_SECTION )
03521 cardReader_->readToNextSection();
03522 numberCones=0;
03523
03524
03525 columnStart = new int [numberColumns_+1];
03526 column = new int [numberColumns_];
03527 int numberErrors = 0;
03528 columnStart[0]=0;
03529 int numberElements=0;
03530 startHash(1);
03531
03532
03533
03534 while ( cardReader_->nextField ( ) == COIN_CONIC_SECTION ) {
03535
03536
03537 if (!strncmp(cardReader_->card(),"CSECTION",8)) {
03538 if (numberElements==columnStart[numberCones]) {
03539 printf("Cone must have at least one column\n");
03540 abort();
03541 }
03542 columnStart[++numberCones]=numberElements;
03543 continue;
03544 }
03545 COINColumnIndex iColumn1;
03546 switch ( cardReader_->mpsType ( ) ) {
03547 case COIN_BLANK_COLUMN:
03548
03549 iColumn1 = findHash ( cardReader_->columnName ( ) , 1 );
03550
03551 if ( iColumn1 >= 0 ) {
03552 column[numberElements++]=iColumn1;
03553 } else {
03554 numberErrors++;
03555 if ( numberErrors < 100 ) {
03556 handler_->message(COIN_MPS_NOMATCHCOL,messages_)
03557 <<cardReader_->columnName()<<cardReader_->cardNumber()<<cardReader_->card()
03558 <<CoinMessageEol;
03559 } else if (numberErrors > 100000) {
03560 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03561 return numberErrors;
03562 }
03563 }
03564 break;
03565 default:
03566 numberErrors++;
03567 if ( numberErrors < 100 ) {
03568 handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
03569 <<cardReader_->card()
03570 <<CoinMessageEol;
03571 } else if (numberErrors > 100000) {
03572 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03573 return numberErrors;
03574 }
03575 }
03576 }
03577 if ( cardReader_->whichSection ( ) == COIN_ENDATA_SECTION ) {
03578
03579 if (!numberElements) {
03580 handler_->message(COIN_MPS_EOF,messages_)<<fileName_
03581 <<CoinMessageEol;
03582 delete [] columnStart;
03583 delete [] column;
03584 columnStart = NULL;
03585 column = NULL;
03586 return -3;
03587 } else {
03588 columnStart[++numberCones]=numberElements;
03589 }
03590 } else {
03591 handler_->message(COIN_MPS_BADFILE1,messages_)<<cardReader_->card()
03592 <<cardReader_->cardNumber()
03593 <<fileName_
03594 <<CoinMessageEol;
03595 delete [] columnStart;
03596 delete [] column;
03597 columnStart = NULL;
03598 column = NULL;
03599 numberCones=0;
03600 return -2;
03601 }
03602
03603 stopHash(1);
03604 return numberErrors;
03605 }