1 /* $Id: CoinMpsIO.cpp 2125 2019-04-10 03:55:09Z stefan $ */
2 // Copyright (C) 2000, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #if defined(_MSC_VER)
7 // Turn off compiler warning about long names
8 #pragma warning(disable : 4786)
9 #endif
10 
11 #include "CoinUtilsConfig.h"
12 
13 #include <cassert>
14 #include <cstdlib>
15 #include <cmath>
16 #include <cfloat>
17 #include <string>
18 #include <cstdio>
19 #include <iostream>
20 
21 #include "CoinMpsIO.hpp"
22 #include "CoinMessage.hpp"
23 #include "CoinHelperFunctions.hpp"
24 #include "CoinModel.hpp"
25 #include "CoinSort.hpp"
26 
27 //#############################################################################
28 // type - 0 normal, 1 INTEL IEEE, 2 other IEEE
29 
30 namespace {
31 
32 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,
33   1.0e-9, 1.0e-10, 1.0e-11, 1.0e-12, 1.0e-13, 1.0e-14, 1.0e-15, 1.0e-16,
34   1.0e-17, 1.0e-18, 1.0e-19, 1.0e-20, 1.0e-21, 1.0e-22, 1.0e-23 };
35 
36 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,
37   1.0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9 };
38 
39 } // end file-local namespace
osi_strtod(char * ptr,char ** output,int type)40 double CoinMpsCardReader::osi_strtod(char *ptr, char **output, int type)
41 {
42 
43   double value = 0.0;
44   char *save = ptr;
45 
46   // take off leading white space
47   while (*ptr == ' ' || *ptr == '\t')
48     ptr++;
49   if (!type) {
50     double sign1 = 1.0;
51     // do + or -
52     if (*ptr == '-') {
53       sign1 = -1.0;
54       ptr++;
55     } else if (*ptr == '+') {
56       ptr++;
57     }
58     // more white space
59     while (*ptr == ' ' || *ptr == '\t')
60       ptr++;
61     char thisChar = 0;
62     while (value < 1.0e30) {
63       thisChar = *ptr;
64       ptr++;
65       if (thisChar >= '0' && thisChar <= '9')
66         value = value * 10.0 + thisChar - '0';
67       else
68         break;
69     }
70     if (value < 1.0e30) {
71       if (thisChar == '.') {
72         // do fraction
73         double value2 = 0.0;
74         int nfrac = 0;
75         while (nfrac < 24) {
76           thisChar = *ptr;
77           ptr++;
78           if (thisChar >= '0' && thisChar <= '9') {
79             value2 = value2 * 10.0 + thisChar - '0';
80             nfrac++;
81           } else {
82             break;
83           }
84         }
85         if (nfrac < 24) {
86           value += value2 * fraction[nfrac];
87         } else {
88           thisChar = 'x'; // force error
89         }
90       }
91       if (thisChar == 'e' || thisChar == 'E') {
92         // exponent
93         int sign2 = 1;
94         // do + or -
95         if (*ptr == '-') {
96           sign2 = -1;
97           ptr++;
98         } else if (*ptr == '+') {
99           ptr++;
100         }
101         int value3 = 0;
102         while (value3 < 1000) {
103           thisChar = *ptr;
104           ptr++;
105           if (thisChar >= '0' && thisChar <= '9') {
106             value3 = value3 * 10 + thisChar - '0';
107           } else {
108             break;
109           }
110         }
111         if (value3 < 300) {
112           value3 *= sign2; // power of 10
113           if (abs(value3) < 10) {
114             // do most common by lookup (for accuracy?)
115             value *= exponent[value3 + 9];
116           } else {
117             value *= pow(10.0, value3);
118           }
119         } else if (sign2 < 0.0) {
120           value = 0.0; // force zero
121         } else {
122           value = COIN_DBL_MAX;
123         }
124       }
125       if (thisChar == 0 || thisChar == '\t' || thisChar == ' ') {
126         // okay
127         *output = ptr;
128       } else {
129         value = osi_strtod(save, output);
130         sign1 = 1.0;
131       }
132     } else {
133       // bad value
134       value = osi_strtod(save, output);
135       sign1 = 1.0;
136     }
137     value *= sign1;
138   } else {
139     // ieee - 3 bytes go to 2
140     assert(sizeof(double) == 8 * sizeof(char));
141     assert(sizeof(unsigned short) == 2 * sizeof(char));
142     unsigned short shortValue[4];
143     *output = ptr + 12; // say okay
144     if (type == 1) {
145       // INTEL
146       for (int i = 3; i >= 0; i--) {
147         int integerValue = 0;
148         char *three = reinterpret_cast< char * >(&integerValue);
149         three[1] = ptr[0];
150         three[2] = ptr[1];
151         three[3] = ptr[2];
152         unsigned short thisValue = 0;
153         // decode 6 bits at a time
154         for (int j = 2; j >= 0; j--) {
155           thisValue = static_cast< unsigned short >(thisValue << 6);
156           char thisChar = ptr[j];
157           if (thisChar >= '0' && thisChar <= '0' + 9) {
158             thisValue = static_cast< unsigned short >(thisValue | (thisChar - '0'));
159           } else if (thisChar >= 'a' && thisChar <= 'a' + 25) {
160             thisValue = static_cast< unsigned short >(thisValue | (thisChar - 'a' + 10));
161           } else if (thisChar >= 'A' && thisChar <= 'A' + 25) {
162             thisValue = static_cast< unsigned short >(thisValue | (thisChar - 'A' + 36));
163           } else if (thisChar >= '*' && thisChar <= '*' + 1) {
164             thisValue = static_cast< unsigned short >(thisValue | (thisChar - '*' + 62));
165           } else {
166             // error
167             *output = save;
168           }
169         }
170         ptr += 3;
171         shortValue[i] = thisValue;
172       }
173     } else {
174       // not INTEL
175       for (int i = 0; i < 4; i++) {
176         int integerValue = 0;
177         char *three = reinterpret_cast< char * >(&integerValue);
178         three[1] = ptr[0];
179         three[2] = ptr[1];
180         three[3] = ptr[2];
181         unsigned short thisValue = 0;
182         // decode 6 bits at a time
183         for (int j = 2; j >= 0; j--) {
184           thisValue = static_cast< unsigned short >(thisValue << 6);
185           char thisChar = ptr[j];
186           if (thisChar >= '0' && thisChar <= '0' + 9) {
187             thisValue = static_cast< unsigned short >(thisValue | (thisChar - '0'));
188           } else if (thisChar >= 'a' && thisChar <= 'a' + 25) {
189             thisValue = static_cast< unsigned short >(thisValue | (thisChar - 'a' + 10));
190           } else if (thisChar >= 'A' && thisChar <= 'A' + 25) {
191             thisValue = static_cast< unsigned short >(thisValue | (thisChar - 'A' + 36));
192           } else if (thisChar >= '*' && thisChar <= '*' + 1) {
193             thisValue = static_cast< unsigned short >(thisValue | (thisChar - '*' + 62));
194           } else {
195             // error
196             *output = save;
197           }
198         }
199         ptr += 3;
200         shortValue[i] = thisValue;
201       }
202     }
203     memcpy(&value, shortValue, sizeof(double));
204   }
205   return value;
206 }
207 // for strings
osi_strtod(char * ptr,char ** output)208 double CoinMpsCardReader::osi_strtod(char *ptr, char **output)
209 {
210   char *save = ptr;
211   double value = -1.0e100;
212   if (!stringsAllowed_) {
213     *output = save;
214   } else {
215     // take off leading white space
216     while (*ptr == ' ' || *ptr == '\t')
217       ptr++;
218     if (*ptr == '=') {
219       strcpy(valueString_, ptr);
220 #define STRING_VALUE -1.234567e-101
221       value = STRING_VALUE;
222       *output = ptr + strlen(ptr);
223     } else {
224       *output = save;
225     }
226   }
227   return value;
228 }
229 //#############################################################################
230 // sections
231 namespace {
232 const static char *section[] = {
233   "", "NAME", "ROW", "COLUMN", "RHS", "RANGES", "BOUNDS", "ENDATA", " ", "QSECTION", "CSECTION",
234   "QUADOBJ", "SOS", "BASIS",
235   " "
236 };
237 
238 // what is allowed in each section - must line up with COINSectionType
239 const static COINMpsType startType[] = {
240   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
241   COIN_N_ROW, COIN_BLANK_COLUMN,
242   COIN_BLANK_COLUMN, COIN_BLANK_COLUMN,
243   COIN_UP_BOUND, COIN_UNKNOWN_MPS_TYPE,
244   COIN_UNKNOWN_MPS_TYPE,
245   COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_S1_BOUND,
246   COIN_BS_BASIS, COIN_UNKNOWN_MPS_TYPE
247 };
248 const static COINMpsType endType[] = {
249   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
250   COIN_BLANK_COLUMN, COIN_UNSET_BOUND,
251   COIN_S1_COLUMN, COIN_S1_COLUMN,
252   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
253   COIN_UNKNOWN_MPS_TYPE,
254   COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_BS_BASIS,
255   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE
256 };
257 const static int allowedLength[] = {
258   0, 0,
259   1, 2,
260   0, 0,
261   2, 0,
262   0, 0,
263   0, 0,
264   0, 2,
265   0
266 };
267 
268 // names of types
269 const static char *mpsTypes[] = {
270   "N", "E", "L", "G",
271   "  ", "S1", "S2", "S3", "  ", "  ", "  ",
272   "  ", "UP", "FX", "LO", "FR", "MI", "PL", "BV", "UI", "LI", "XX", "SC",
273   "X1", "X2", "BS", "XL", "XU", "LL", "UL", "  "
274 };
275 } // namespace {
276 
cleanCard()277 int CoinMpsCardReader::cleanCard()
278 {
279   char *getit;
280   getit = input_->gets(card_, MAX_CARD_LENGTH);
281 
282   if (getit) {
283     cardNumber_++;
284     unsigned char *lastNonBlank = reinterpret_cast< unsigned char * >(card_ - 1);
285     unsigned char *image = reinterpret_cast< unsigned char * >(card_);
286     bool tabs = false;
287     while (*image != '\0') {
288       if (*image != '\t' && *image < ' ') {
289         break;
290       } else if (*image != '\t' && *image != ' ') {
291         lastNonBlank = image;
292       } else if (*image == '\t') {
293         tabs = true;
294       }
295       image++;
296     }
297     *(lastNonBlank + 1) = '\0';
298     if (tabs && section_ == COIN_BOUNDS_SECTION && !freeFormat_ && eightChar_) {
299       int length = static_cast< int >(lastNonBlank + 1 - reinterpret_cast< unsigned char * >(card_));
300       assert(length < 81);
301       memcpy(card_ + 82, card_, length);
302       int pos[] = { 1, 4, 14, 24, 1000 };
303       int put = 0;
304       int tab = 0;
305       for (int i = 0; i < length; i++) {
306         char look = card_[i + 82];
307         if (look != '\t') {
308           card_[put++] = look;
309         } else {
310           // count on to next
311           for (; tab < 5; tab++) {
312             if (put < pos[tab]) {
313               while (put < pos[tab])
314                 card_[put++] = ' ';
315               break;
316             }
317           }
318         }
319       }
320       card_[put++] = '\0';
321     }
322     return 0;
323   } else {
324     return 1;
325   }
326 }
327 
328 char *
nextBlankOr(char * image)329 CoinMpsCardReader::nextBlankOr(char *image)
330 {
331   char *saveImage = image;
332   while (1) {
333     if (*image == ' ' || *image == '\t') {
334       break;
335     }
336     if (*image == '\0')
337       return NULL;
338     image++;
339   }
340   // Allow for floating - or +.  Will fail if user has that as row name!!
341   if (image - saveImage == 1 && (*saveImage == '+' || *saveImage == '-')) {
342     while (*image == ' ' || *image == '\t') {
343       image++;
344     }
345     image = nextBlankOr(image);
346   }
347   return image;
348 }
349 
350 // Read to NAME card - return nonzero if bad
351 COINSectionType
readToNextSection()352 CoinMpsCardReader::readToNextSection()
353 {
354   bool found = false;
355 
356   while (!found) {
357     // need new image
358 
359     if (cleanCard()) {
360       section_ = COIN_EOF_SECTION;
361       break;
362     }
363     if (!strncmp(card_, "NAME", 4) || !strncmp(card_, "TIME", 4) || !strncmp(card_, "BASIS", 5) || !strncmp(card_, "STOCH", 5)) {
364       section_ = COIN_NAME_SECTION;
365       char *next = card_ + 5;
366       position_ = eol_ = card_ + strlen(card_);
367 
368       handler_->message(COIN_MPS_LINE, messages_) << cardNumber_
369                                                   << card_ << CoinMessageEol;
370       while (next < eol_) {
371         if (*next == ' ' || *next == '\t') {
372           next++;
373         } else {
374           break;
375         }
376       }
377       if (next < eol_) {
378         char *nextBlank = nextBlankOr(next);
379         char save;
380 
381         if (nextBlank) {
382           save = *nextBlank;
383           *nextBlank = '\0';
384           strcpy(columnName_, next);
385           *nextBlank = save;
386           if (strstr(nextBlank, "FREEIEEE")) {
387             freeFormat_ = true;
388             // see if intel
389             ieeeFormat_ = 1;
390             double value = 1.0;
391             char x[8];
392             memcpy(x, &value, 8);
393             if (x[0] == 63) {
394               ieeeFormat_ = 2; // not intel
395             } else {
396               assert(x[0] == 0);
397             }
398           } else if (strstr(nextBlank, "FREE")) {
399             freeFormat_ = true;
400           } else if (strstr(nextBlank, "VALUES")) {
401             // basis is always free - just use this to communicate back
402             freeFormat_ = true;
403           } else if (strstr(nextBlank, "IEEE")) {
404             // see if intel
405             ieeeFormat_ = 1;
406             double value = 1.0;
407             char x[8];
408             memcpy(x, &value, 8);
409             if (x[0] == 63) {
410               ieeeFormat_ = 2; // not intel
411             } else {
412               assert(x[0] == 0);
413             }
414           }
415         } else {
416           strcpy(columnName_, next);
417         }
418       } else {
419         strcpy(columnName_, "no_name");
420       }
421       break;
422     } else if (card_[0] != '*' && card_[0] != '#') {
423       // not a comment
424       int i;
425 
426       handler_->message(COIN_MPS_LINE, messages_) << cardNumber_
427                                                   << card_ << CoinMessageEol;
428       for (i = COIN_ROW_SECTION; i < COIN_UNKNOWN_SECTION; i++) {
429         if (!strncmp(card_, section[i], strlen(section[i]))) {
430           break;
431         }
432       }
433       position_ = card_;
434       eol_ = card_;
435       section_ = static_cast< COINSectionType >(i);
436       break;
437     }
438   }
439   return section_;
440 }
441 
CoinMpsCardReader(CoinFileInput * input,CoinMpsIO * reader)442 CoinMpsCardReader::CoinMpsCardReader(CoinFileInput *input,
443   CoinMpsIO *reader)
444 {
445   memset(card_, 0, MAX_CARD_LENGTH);
446   position_ = card_;
447   eol_ = card_;
448   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
449   memset(rowName_, 0, COIN_MAX_FIELD_LENGTH);
450   memset(columnName_, 0, COIN_MAX_FIELD_LENGTH);
451   value_ = 0.0;
452   input_ = input;
453   section_ = COIN_EOF_SECTION;
454   cardNumber_ = 0;
455   freeFormat_ = false;
456   ieeeFormat_ = 0;
457   eightChar_ = true;
458   reader_ = reader;
459   handler_ = reader_->messageHandler();
460   messages_ = reader_->messages();
461   memset(valueString_, 0, COIN_MAX_FIELD_LENGTH);
462   stringsAllowed_ = false;
463 }
464 //  ~CoinMpsCardReader.  Destructor
~CoinMpsCardReader()465 CoinMpsCardReader::~CoinMpsCardReader()
466 {
467   delete input_;
468 }
469 
strcpyAndCompress(char * to,const char * from)470 void CoinMpsCardReader::strcpyAndCompress(char *to, const char *from)
471 {
472   int n = static_cast< int >(strlen(from));
473   int i;
474   int nto = 0;
475 
476   for (i = 0; i < n; i++) {
477     if (from[i] != ' ') {
478       to[nto++] = from[i];
479     }
480   }
481   if (!nto)
482     to[nto++] = ' ';
483   to[nto] = '\0';
484 }
485 
486 //  nextField
487 COINSectionType
nextField()488 CoinMpsCardReader::nextField()
489 {
490   mpsType_ = COIN_BLANK_COLUMN;
491   // find next non blank character
492   char *next = position_;
493 
494   while (next != eol_) {
495     if (*next == ' ' || *next == '\t') {
496       next++;
497     } else {
498       break;
499     }
500   }
501   bool gotCard;
502 
503   if (next == eol_) {
504     gotCard = false;
505   } else {
506     gotCard = true;
507   }
508   while (!gotCard) {
509     // need new image
510 
511     if (cleanCard()) {
512       return COIN_EOF_SECTION;
513     }
514     if (card_[0] == ' ' || card_[0] == '\0') {
515       // not a section or comment
516       position_ = card_;
517       eol_ = card_ + strlen(card_);
518       // get mps type and column name
519       // scan to first non blank
520       next = card_;
521       while (next != eol_) {
522         if (*next == ' ' || *next == '\t') {
523           next++;
524         } else {
525           break;
526         }
527       }
528       if (next != eol_) {
529         char *nextBlank = nextBlankOr(next);
530         int nchar;
531 
532         if (nextBlank) {
533           nchar = static_cast< int >(nextBlank - next);
534         } else {
535           nchar = -1;
536         }
537         mpsType_ = COIN_BLANK_COLUMN;
538         // special coding if RHS or RANGES, not free format and blanks
539         if ((section_ != COIN_RHS_SECTION
540               && section_ != COIN_RANGES_SECTION)
541           || freeFormat_ || strncmp(card_ + 4, "        ", 8)) {
542           // if columns section only look for first field if MARKER
543           if (section_ == COIN_COLUMN_SECTION
544             && !strstr(next, "'MARKER'"))
545             nchar = -1;
546           if (section_ == COIN_SOS_SECTION) {
547             if (!strncmp(card_, " S1", 3)) {
548               mpsType_ = COIN_S1_BOUND;
549               break;
550             } else if (!strncmp(card_, " S2", 3)) {
551               mpsType_ = COIN_S2_BOUND;
552               break;
553             }
554           }
555           if (nchar == allowedLength[section_]) {
556             //could be a type
557             int i;
558 
559             for (i = startType[section_]; i < endType[section_]; i++) {
560               if (!strncmp(next, mpsTypes[i], nchar)) {
561                 mpsType_ = static_cast< COINMpsType >(i);
562                 break;
563               }
564             }
565             if (mpsType_ != COIN_BLANK_COLUMN) {
566               //we know all we need so we can skip over
567               next = nextBlank;
568               while (next != eol_) {
569                 if (*next == ' ' || *next == '\t') {
570                   next++;
571                 } else {
572                   break;
573                 }
574               }
575               if (next == eol_) {
576                 // error
577                 position_ = eol_;
578                 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
579               } else {
580                 nextBlank = nextBlankOr(next);
581               }
582             } else if (section_ == COIN_BOUNDS_SECTION) {
583               // should have been something - but just fix LI problem
584               // set to something illegal
585               if (card_[0] == ' ' && card_[3] == ' ' && (card_[1] != ' ' || card_[2] != ' ')) {
586                 mpsType_ = COIN_S3_COLUMN;
587                 //we know all we need so we can skip over
588                 next = nextBlank;
589                 while (next != eol_) {
590                   if (*next == ' ' || *next == '\t') {
591                     next++;
592                   } else {
593                     break;
594                   }
595                 }
596                 if (next == eol_) {
597                   // error
598                   position_ = eol_;
599                   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
600                 } else {
601                   nextBlank = nextBlankOr(next);
602                 }
603               }
604             }
605           }
606           if (mpsType_ != COIN_UNKNOWN_MPS_TYPE) {
607             // special coding if BOUND, not free format and blanks
608             if (section_ != COIN_BOUNDS_SECTION || freeFormat_ || strncmp(card_ + 4, "        ", 8)) {
609               char save = '?';
610 
611               if (!freeFormat_ && eightChar_ && next == card_ + 4) {
612                 if (eol_ - next >= 8) {
613                   if (*(next + 8) != ' ' && *(next + 8) != '\0') {
614                     eightChar_ = false;
615                   } else {
616                     nextBlank = next + 8;
617                   }
618                   if (nextBlank) {
619                     save = *nextBlank;
620                     *nextBlank = '\0';
621                   }
622                 } else {
623                   nextBlank = NULL;
624                 }
625               } else {
626                 if (nextBlank) {
627                   save = *nextBlank;
628                   *nextBlank = '\0';
629                 }
630               }
631               strcpyAndCompress(columnName_, next);
632               if (nextBlank) {
633                 *nextBlank = save;
634                 // on to next
635                 next = nextBlank;
636               } else {
637                 next = eol_;
638               }
639             } else {
640               // blank bounds name
641               strcpy(columnName_, "        ");
642             }
643             while (next != eol_) {
644               if (*next == ' ' || *next == '\t') {
645                 next++;
646               } else {
647                 break;
648               }
649             }
650             if (next == eol_) {
651               // error unless row section or conic section
652               position_ = eol_;
653               value_ = -1.0e100;
654               if (section_ != COIN_ROW_SECTION && section_ != COIN_CONIC_SECTION)
655                 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
656               else
657                 return section_;
658             } else {
659               nextBlank = nextBlankOr(next);
660               //if (section_==COIN_CONIC_SECTION)
661             }
662             if (section_ != COIN_ROW_SECTION) {
663               char save = '?';
664 
665               if (!freeFormat_ && eightChar_ && next == card_ + 14) {
666                 if (eol_ - next >= 8) {
667                   if (*(next + 8) != ' ' && *(next + 8) != '\0') {
668                     eightChar_ = false;
669                   } else {
670                     nextBlank = next + 8;
671                   }
672                   save = *nextBlank;
673                   *nextBlank = '\0';
674                 } else {
675                   nextBlank = NULL;
676                 }
677               } else {
678                 if (nextBlank) {
679                   save = *nextBlank;
680                   *nextBlank = '\0';
681                 }
682               }
683               strcpyAndCompress(rowName_, next);
684               if (nextBlank) {
685                 *nextBlank = save;
686                 // on to next
687                 next = nextBlank;
688               } else {
689                 next = eol_;
690               }
691               while (next != eol_) {
692                 if (*next == ' ' || *next == '\t') {
693                   next++;
694                 } else {
695                   break;
696                 }
697               }
698               // special coding for markers
699               if (section_ == COIN_COLUMN_SECTION && !strncmp(rowName_, "'MARKER'", 8) && next != eol_) {
700                 if (!strncmp(next, "'INTORG'", 8)) {
701                   mpsType_ = COIN_INTORG;
702                 } else if (!strncmp(next, "'INTEND'", 8)) {
703                   mpsType_ = COIN_INTEND;
704                 } else if (!strncmp(next, "'SOSORG'", 8)) {
705                   if (mpsType_ == COIN_BLANK_COLUMN)
706                     mpsType_ = COIN_S1_COLUMN;
707                 } else if (!strncmp(next, "'SOSEND'", 8)) {
708                   mpsType_ = COIN_SOSEND;
709                 } else {
710                   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
711                 }
712                 position_ = eol_;
713                 return section_;
714               }
715               if (next == eol_) {
716                 // error unless bounds or basis
717                 position_ = eol_;
718                 if (section_ != COIN_BOUNDS_SECTION) {
719                   if (section_ != COIN_BASIS_SECTION)
720                     mpsType_ = COIN_UNKNOWN_MPS_TYPE;
721                   value_ = -1.0e100;
722                 } else {
723                   value_ = 0.0;
724                 }
725               } else {
726                 nextBlank = nextBlankOr(next);
727                 if (nextBlank) {
728                   save = *nextBlank;
729                   *nextBlank = '\0';
730                 }
731                 char *after;
732                 value_ = osi_strtod(next, &after, ieeeFormat_);
733                 // see if error
734                 if (after > next) {
735                   if (nextBlank) {
736                     *nextBlank = save;
737                     position_ = nextBlank;
738                   } else {
739                     position_ = eol_;
740                   }
741                 } else {
742                   // error
743                   position_ = eol_;
744                   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
745                   value_ = -1.0e100;
746                 }
747               }
748             }
749           }
750         } else {
751           //blank name in RHS or RANGES
752           strcpy(columnName_, "        ");
753           char save = '?';
754 
755           if (!freeFormat_ && eightChar_ && next == card_ + 14) {
756             if (eol_ - next >= 8) {
757               if (*(next + 8) != ' ' && *(next + 8) != '\0') {
758                 eightChar_ = false;
759               } else {
760                 nextBlank = next + 8;
761               }
762               save = *nextBlank;
763               *nextBlank = '\0';
764             } else {
765               nextBlank = NULL;
766             }
767           } else {
768             if (nextBlank) {
769               save = *nextBlank;
770               *nextBlank = '\0';
771             }
772           }
773           strcpyAndCompress(rowName_, next);
774           if (nextBlank) {
775             *nextBlank = save;
776             // on to next
777             next = nextBlank;
778           } else {
779             next = eol_;
780           }
781           while (next != eol_) {
782             if (*next == ' ' || *next == '\t') {
783               next++;
784             } else {
785               break;
786             }
787           }
788           if (next == eol_) {
789             // error
790             position_ = eol_;
791             value_ = -1.0e100;
792             mpsType_ = COIN_UNKNOWN_MPS_TYPE;
793           } else {
794             nextBlank = nextBlankOr(next);
795             value_ = -1.0e100;
796             if (nextBlank) {
797               save = *nextBlank;
798               *nextBlank = '\0';
799             }
800             char *after;
801             value_ = osi_strtod(next, &after, ieeeFormat_);
802             // see if error
803             if (after > next) {
804               if (nextBlank) {
805                 *nextBlank = save;
806                 position_ = nextBlank;
807               } else {
808                 position_ = eol_;
809               }
810             } else {
811               // error
812               position_ = eol_;
813               mpsType_ = COIN_UNKNOWN_MPS_TYPE;
814               value_ = -1.0e100;
815             }
816           }
817         }
818       } else {
819         // blank
820         continue;
821       }
822       return section_;
823     } else if (card_[0] != '*') {
824       // not a comment
825       int i;
826 
827       handler_->message(COIN_MPS_LINE, messages_) << cardNumber_
828                                                   << card_ << CoinMessageEol;
829       for (i = COIN_ROW_SECTION; i < COIN_UNKNOWN_SECTION; i++) {
830         if (!strncmp(card_, section[i], strlen(section[i]))) {
831           break;
832         }
833       }
834       position_ = card_;
835       eol_ = card_;
836       section_ = static_cast< COINSectionType >(i);
837       return section_;
838     } else {
839       // comment
840     }
841   }
842   // we only get here for second field (we could even allow more???)
843   {
844     char save = '?';
845     char *nextBlank = nextBlankOr(next);
846 
847     if (!freeFormat_ && eightChar_ && next == card_ + 39) {
848       if (eol_ - next >= 8) {
849         if (*(next + 8) != ' ' && *(next + 8) != '\0') {
850           eightChar_ = false;
851         } else {
852           nextBlank = next + 8;
853         }
854         save = *nextBlank;
855         *nextBlank = '\0';
856       } else {
857         nextBlank = NULL;
858       }
859     } else {
860       if (nextBlank) {
861         save = *nextBlank;
862         *nextBlank = '\0';
863       }
864     }
865     strcpyAndCompress(rowName_, next);
866     // on to next
867     if (nextBlank) {
868       *nextBlank = save;
869       next = nextBlank;
870     } else {
871       next = eol_;
872     }
873     while (next != eol_) {
874       if (*next == ' ' || *next == '\t') {
875         next++;
876       } else {
877         break;
878       }
879     }
880     if (next == eol_ && section_ != COIN_SOS_SECTION) {
881       // error
882       position_ = eol_;
883       mpsType_ = COIN_UNKNOWN_MPS_TYPE;
884     } else {
885       nextBlank = nextBlankOr(next);
886     }
887     if (nextBlank) {
888       save = *nextBlank;
889       *nextBlank = '\0';
890     }
891     //value_ = -1.0e100;
892     char *after;
893     value_ = osi_strtod(next, &after, ieeeFormat_);
894     // see if error
895     if (after > next) {
896       if (nextBlank) {
897         *nextBlank = save;
898         position_ = nextBlank;
899       } else {
900         position_ = eol_;
901       }
902     } else {
903       // error
904       position_ = eol_;
905       if (mpsType_ != COIN_S1_BOUND && mpsType_ != COIN_S2_BOUND)
906         mpsType_ = COIN_UNKNOWN_MPS_TYPE;
907       value_ = -1.0e100;
908     }
909   }
910   return section_;
911 }
912 static char *
nextNonBlank(char * image)913 nextNonBlank(char *image)
914 {
915   while (1) {
916     if (*image != ' ' && *image != '\t')
917       break;
918     else
919       image++;
920   }
921   if (*image == '\0')
922     image = NULL;
923   return image;
924 }
925 /** Gets next field for .gms file and returns type.
926     -1 - EOF
927     0 - what we expected (and processed so pointer moves past)
928     1 - not what we expected
929     2 - equation type when expecting value name pair
930     leading blanks always ignored
931     input types
932     0 - anything - stops on non blank card
933     1 - name (in columnname)
934     2 - value
935     3 - value name pair
936     4 - equation type
937     5 - ;
938 */
nextGmsField(int expectedType)939 int CoinMpsCardReader::nextGmsField(int expectedType)
940 {
941   int returnCode = -1;
942   bool good = false;
943   switch (expectedType) {
944   case 0:
945     // 0 - May get * in first column or anything
946     if (cleanCard())
947       return -1;
948     while (!strlen(card_)) {
949       if (cleanCard())
950         return -1;
951     }
952     eol_ = card_ + strlen(card_);
953     position_ = card_;
954     returnCode = 0;
955     break;
956   case 1:
957     // 1 - expect name
958     while (!good) {
959       position_ = nextNonBlank(position_);
960       if (position_ == NULL) {
961         if (cleanCard())
962           return -1;
963         eol_ = card_ + strlen(card_);
964         position_ = card_;
965       } else {
966         good = true;
967         char nextChar = *position_;
968         if ((nextChar >= 'a' && nextChar <= 'z') || (nextChar >= 'A' && nextChar <= 'Z')) {
969           returnCode = 0;
970           char *next = position_;
971           while (*next != ',' && *next != ';' && *next != '=' && *next != ' '
972             && *next != '\t' && *next != '-' && *next != '+' && *next >= 32)
973             next++;
974           if (next) {
975             int length = static_cast< int >(next - position_);
976             strncpy(columnName_, position_, length);
977             columnName_[length] = '\0';
978           } else {
979             strcpy(columnName_, position_);
980             next = eol_;
981           }
982           position_ = next;
983         } else {
984           returnCode = 1;
985         }
986       }
987     }
988     break;
989   case 2:
990     // 2 - expect value
991     while (!good) {
992       position_ = nextNonBlank(position_);
993       if (position_ == NULL) {
994         if (cleanCard())
995           return -1;
996         eol_ = card_ + strlen(card_);
997         position_ = card_;
998       } else {
999         good = true;
1000         char nextChar = *position_;
1001         if ((nextChar >= '0' && nextChar <= '9') || nextChar == '+' || nextChar == '-') {
1002           returnCode = 0;
1003           char *next = position_;
1004           while (*next != ',' && *next != ';' && *next != '=' && *next != ' '
1005             && *next != '\t' && *next >= 32)
1006             next++;
1007           if (next) {
1008             int length = static_cast< int >(next - position_);
1009             strncpy(rowName_, position_, length);
1010             rowName_[length] = '\0';
1011           } else {
1012             strcpy(rowName_, position_);
1013             next = eol_;
1014           }
1015           value_ = -1.0e100;
1016           sscanf(rowName_, "%lg", &value_);
1017           position_ = next;
1018         } else {
1019           returnCode = 1;
1020         }
1021       }
1022     }
1023     break;
1024   case 3:
1025     // 3 - expect value name pair
1026     while (!good) {
1027       position_ = nextNonBlank(position_);
1028       char *savePosition = position_;
1029       if (position_ == NULL) {
1030         if (cleanCard())
1031           return -1;
1032         eol_ = card_ + strlen(card_);
1033         position_ = card_;
1034         savePosition = position_;
1035       } else {
1036         good = true;
1037         value_ = 1.0;
1038         char nextChar = *position_;
1039         returnCode = 0;
1040         if ((nextChar >= '0' && nextChar <= '9') || nextChar == '+' || nextChar == '-') {
1041           char *next;
1042           int put = 0;
1043           if (nextChar == '+' || nextChar == '-') {
1044             rowName_[0] = nextChar;
1045             put = 1;
1046             next = position_ + 1;
1047             while (*next == ' ' || *next == '\t')
1048               next++;
1049             if ((*next >= 'a' && *next <= 'z') || (*next >= 'A' && *next <= 'Z')) {
1050               // name - set value
1051               if (nextChar == '+')
1052                 value_ = 1.0;
1053               else
1054                 value_ = -1.0;
1055               position_ = next;
1056             } else if ((*next >= '0' && *next <= '9') || *next == '+' || *next == '-') {
1057               rowName_[put++] = *next;
1058               next++;
1059               while (*next != ' ' && *next != '\t' && *next != '*') {
1060                 rowName_[put++] = *next;
1061                 next++;
1062               }
1063               assert(*next == '*');
1064               next++;
1065               rowName_[put] = '\0';
1066               value_ = -1.0e100;
1067               sscanf(rowName_, "%lg", &value_);
1068               position_ = next;
1069             } else {
1070               returnCode = 1;
1071             }
1072           } else {
1073             // number
1074             char *next = nextBlankOr(position_);
1075             // but could be *
1076             char *next2 = strchr(position_, '*');
1077             if (next2 && next2 - position_ < next - position_) {
1078               next = next2;
1079             }
1080             int length = static_cast< int >(next - position_);
1081             strncpy(rowName_, position_, length);
1082             rowName_[length] = '\0';
1083             value_ = -1.0e100;
1084             sscanf(rowName_, "%lg", &value_);
1085             position_ = next;
1086           }
1087         } else if ((nextChar >= 'a' && nextChar <= 'z') || (nextChar >= 'A' && nextChar <= 'Z')) {
1088           // name so take value as 1.0
1089         } else if (nextChar == '=') {
1090           returnCode = 2;
1091           position_ = savePosition;
1092         } else {
1093           returnCode = 1;
1094           position_ = savePosition;
1095         }
1096         if ((*position_) == '*')
1097           position_++;
1098         position_ = nextNonBlank(position_);
1099         if (!returnCode) {
1100           char nextChar = *position_;
1101           if ((nextChar >= 'a' && nextChar <= 'z') || (nextChar >= 'A' && nextChar <= 'Z')) {
1102             char *next = nextBlankOr(position_);
1103             if (next) {
1104               int length = static_cast< int >(next - position_);
1105               strncpy(columnName_, position_, length);
1106               columnName_[length] = '\0';
1107             } else {
1108               strcpy(columnName_, position_);
1109               next = eol_;
1110             }
1111             position_ = next;
1112           } else {
1113             returnCode = 1;
1114             position_ = savePosition;
1115           }
1116         }
1117       }
1118     }
1119     break;
1120   case 4:
1121     // 4 - expect equation type
1122     while (!good) {
1123       position_ = nextNonBlank(position_);
1124       if (position_ == NULL) {
1125         if (cleanCard())
1126           return -1;
1127         eol_ = card_ + strlen(card_);
1128         position_ = card_;
1129       } else {
1130         good = true;
1131         char nextChar = *position_;
1132         if (nextChar == '=') {
1133           returnCode = 0;
1134           char *next = nextBlankOr(position_);
1135           int length = static_cast< int >(next - position_);
1136           strncpy(rowName_, position_, length);
1137           rowName_[length] = '\0';
1138           position_ = next;
1139         } else {
1140           returnCode = 1;
1141         }
1142       }
1143     }
1144     break;
1145   case 5:
1146     // 5 - ; expected
1147     while (!good) {
1148       position_ = nextNonBlank(position_);
1149       if (position_ == NULL) {
1150         if (cleanCard())
1151           return -1;
1152         eol_ = card_ + strlen(card_);
1153         position_ = card_;
1154       } else {
1155         good = true;
1156         char nextChar = *position_;
1157         if (nextChar == ';') {
1158           returnCode = 0;
1159           char *next = nextBlankOr(position_);
1160           if (!next)
1161             next = eol_;
1162           position_ = next;
1163         } else {
1164           returnCode = 1;
1165         }
1166       }
1167     }
1168     break;
1169   }
1170   return returnCode;
1171 }
1172 
1173 //#############################################################################
1174 
1175 namespace {
1176 const int mmult[] = {
1177   262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
1178   241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
1179   221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
1180   201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
1181   181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
1182   161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
1183   141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
1184   122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
1185   103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
1186   82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
1187 };
1188 
hash(const char * name,int maxsiz,int length)1189 int hash(const char *name, int maxsiz, int length)
1190 {
1191 
1192   int n = 0;
1193   int j;
1194 
1195   for (j = 0; j < length; ++j) {
1196     int iname = name[j];
1197 
1198     n += mmult[j] * iname;
1199   }
1200   return (abs(n) % maxsiz); /* integer abs */
1201 }
1202 } // end file-local namespace
1203 
1204 // Define below if you are reading a Cnnnnnn file
1205 // Will not do row names (for electricfence)
1206 //#define NONAMES
1207 #ifndef NONAMES
1208 //  startHash.  Creates hash list for names
startHash(char ** names,const COINColumnIndex number,int section)1209 void CoinMpsIO::startHash(char **names, const COINColumnIndex number, int section)
1210 {
1211   names_[section] = names;
1212   numberHash_[section] = number;
1213   startHash(section);
1214 }
startHash(int section) const1215 void CoinMpsIO::startHash(int section) const
1216 {
1217   char **names = names_[section];
1218   COINColumnIndex number = numberHash_[section];
1219   COINColumnIndex i;
1220   COINColumnIndex maxhash = 4 * number;
1221   COINColumnIndex ipos, iput;
1222 
1223   //hash_=(CoinHashLink *) malloc(maxhash*sizeof(CoinHashLink));
1224   hash_[section] = new CoinHashLink[maxhash];
1225 
1226   CoinHashLink *hashThis = hash_[section];
1227 
1228   for (i = 0; i < maxhash; i++) {
1229     hashThis[i].index = -1;
1230     hashThis[i].next = -1;
1231   }
1232 
1233   /*
1234    * Initialize the hash table.  Only the index of the first name that
1235    * hashes to a value is entered in the table; subsequent names that
1236    * collide with it are not entered.
1237    */
1238   for (i = 0; i < number; ++i) {
1239     char *thisName = names[i];
1240     int length = static_cast< int >(strlen(thisName));
1241 
1242     ipos = hash(thisName, maxhash, length);
1243     if (hashThis[ipos].index == -1) {
1244       hashThis[ipos].index = i;
1245     }
1246   }
1247 
1248   /*
1249    * Now take care of the names that collided in the preceding loop,
1250    * by finding some other entry in the table for them.
1251    * Since there are as many entries in the table as there are names,
1252    * there must be room for them.
1253    */
1254   iput = -1;
1255   for (i = 0; i < number; ++i) {
1256     char *thisName = names[i];
1257     int length = static_cast< int >(strlen(thisName));
1258 
1259     ipos = hash(thisName, maxhash, length);
1260 
1261     while (1) {
1262       COINColumnIndex j1 = hashThis[ipos].index;
1263 
1264       if (j1 == i)
1265         break;
1266       else {
1267         char *thisName2 = names[j1];
1268 
1269         if (strcmp(thisName, thisName2) == 0) {
1270           printf("** duplicate name %s\n", names[i]);
1271           break;
1272         } else {
1273           COINColumnIndex k = hashThis[ipos].next;
1274 
1275           if (k == -1) {
1276             while (1) {
1277               ++iput;
1278               if (iput > number) {
1279                 printf("** too many names\n");
1280                 break;
1281               }
1282               if (hashThis[iput].index == -1) {
1283                 break;
1284               }
1285             }
1286             hashThis[ipos].next = iput;
1287             hashThis[iput].index = i;
1288             break;
1289           } else {
1290             ipos = k;
1291             /* nothing worked - try it again */
1292           }
1293         }
1294       }
1295     }
1296   }
1297 }
1298 
1299 //  stopHash.  Deletes hash storage
stopHash(int section)1300 void CoinMpsIO::stopHash(int section)
1301 {
1302   delete[] hash_[section];
1303   hash_[section] = NULL;
1304 }
1305 
1306 //  findHash.  -1 not found
1307 COINColumnIndex
findHash(const char * name,int section) const1308 CoinMpsIO::findHash(const char *name, int section) const
1309 {
1310   COINColumnIndex found = -1;
1311 
1312   char **names = names_[section];
1313   CoinHashLink *hashThis = hash_[section];
1314   COINColumnIndex maxhash = 4 * numberHash_[section];
1315   COINColumnIndex ipos;
1316 
1317   /* default if we don't find anything */
1318   if (!maxhash)
1319     return -1;
1320   int length = static_cast< int >(strlen(name));
1321 
1322   ipos = hash(name, maxhash, length);
1323   while (1) {
1324     COINColumnIndex j1 = hashThis[ipos].index;
1325 
1326     if (j1 >= 0) {
1327       char *thisName2 = names[j1];
1328 
1329       if (strcmp(name, thisName2) != 0) {
1330         COINColumnIndex k = hashThis[ipos].next;
1331 
1332         if (k != -1)
1333           ipos = k;
1334         else
1335           break;
1336       } else {
1337         found = j1;
1338         break;
1339       }
1340     } else {
1341       found = -1;
1342       break;
1343     }
1344   }
1345   return found;
1346 }
1347 #else
1348 // Version when we know images are C/Rnnnnnn
1349 //  startHash.  Creates hash list for names
startHash(char ** names,const COINColumnIndex number,int section)1350 void CoinMpsIO::startHash(char **names, const COINColumnIndex number, int section)
1351 {
1352   numberHash_[section] = number;
1353   names_[section] = names;
1354 }
startHash(int section) const1355 void CoinMpsIO::startHash(int section) const
1356 {
1357 }
1358 
1359 //  stopHash.  Deletes hash storage
stopHash(int section)1360 void CoinMpsIO::stopHash(int section)
1361 {
1362 }
1363 
1364 //  findHash.  -1 not found
1365 COINColumnIndex
findHash(const char * name,int section) const1366 CoinMpsIO::findHash(const char *name, int section) const
1367 {
1368   COINColumnIndex found = atoi(name + 1);
1369   if (!strcmp(name, "OBJROW"))
1370     found = numberHash_[section] - 1;
1371   return found;
1372 }
1373 #endif
1374 //------------------------------------------------------------------
1375 // Get value for infinity
1376 //------------------------------------------------------------------
getInfinity() const1377 double CoinMpsIO::getInfinity() const
1378 {
1379   return infinity_;
1380 }
1381 //------------------------------------------------------------------
1382 // Set value for infinity
1383 //------------------------------------------------------------------
setInfinity(double value)1384 void CoinMpsIO::setInfinity(double value)
1385 {
1386   if (value >= 1.020) {
1387     infinity_ = value;
1388   } else {
1389     handler_->message(COIN_MPS_ILLEGAL, messages_) << "infinity"
1390                                                    << value
1391                                                    << CoinMessageEol;
1392   }
1393 }
1394 // Set file name
setFileName(const char * name)1395 void CoinMpsIO::setFileName(const char *name)
1396 {
1397   free(fileName_);
1398   fileName_ = CoinStrdup(name);
1399 }
1400 // Get file name
getFileName() const1401 const char *CoinMpsIO::getFileName() const
1402 {
1403   return fileName_;
1404 }
1405 // Deal with filename - +1 if new, 0 if same as before, -1 if error
dealWithFileName(const char * filename,const char * extension,CoinFileInput * & input)1406 int CoinMpsIO::dealWithFileName(const char *filename, const char *extension,
1407   CoinFileInput *&input)
1408 {
1409   if (input != 0) {
1410     delete input;
1411     input = 0;
1412   }
1413 
1414   int goodFile = 0;
1415 
1416   if (!fileName_ || (filename != NULL && strcmp(filename, fileName_))) {
1417     if (filename == NULL) {
1418       handler_->message(COIN_MPS_FILE, messages_) << "NULL"
1419                                                   << CoinMessageEol;
1420       return -1;
1421     }
1422     goodFile = -1;
1423     // looks new name
1424     char newName[400];
1425     if (strcmp(filename, "stdin") && strcmp(filename, "-")) {
1426       if (extension && strlen(extension)) {
1427         // There was an extension - but see if user gave .xxx
1428         int i = static_cast< int >(strlen(filename)) - 1;
1429         strcpy(newName, filename);
1430         bool foundDot = false;
1431         for (; i >= 0; i--) {
1432           char character = filename[i];
1433           if (character == '/' || character == '\\') {
1434             break;
1435           } else if (character == '.') {
1436             foundDot = true;
1437             break;
1438           }
1439         }
1440         if (!foundDot) {
1441           strcat(newName, ".");
1442           strcat(newName, extension);
1443         }
1444       } else {
1445         // no extension
1446         strcpy(newName, filename);
1447       }
1448     } else {
1449       strcpy(newName, "stdin");
1450     }
1451     // See if new name
1452     if (fileName_ && !strcmp(newName, fileName_)) {
1453       // old name
1454       return 0;
1455     } else {
1456       // new file
1457       free(fileName_);
1458       fileName_ = CoinStrdup(newName);
1459       if (strcmp(fileName_, "stdin")) {
1460 
1461         // be clever with extensions here
1462         std::string fname = fileName_;
1463         bool readable = fileCoinReadable(fname);
1464         if (!readable)
1465           goodFile = -1;
1466         else {
1467           input = CoinFileInput::create(fname);
1468           goodFile = 1;
1469         }
1470       } else {
1471         // only plain file at present
1472         input = CoinFileInput::create("stdin");
1473         goodFile = 1;
1474       }
1475     }
1476   } else {
1477     // same as before
1478     // reset section ?
1479     goodFile = 0;
1480   }
1481   if (goodFile < 0)
1482     handler_->message(COIN_MPS_FILE, messages_) << fileName_
1483                                                 << CoinMessageEol;
1484   return goodFile;
1485 }
1486 /* objective offset - this is RHS entry for objective row */
objectiveOffset() const1487 double CoinMpsIO::objectiveOffset() const
1488 {
1489   return objectiveOffset_;
1490 }
1491 /*
1492   Prior to June 2007, this was set to 1e30. But that causes problems in
1493   some of the cut generators --- they need to see finite infinity in order
1494   to work properly.
1495 */
1496 #define MAX_INTEGER COIN_DBL_MAX
1497 // Sets default upper bound for integer variables
setDefaultBound(int value)1498 void CoinMpsIO::setDefaultBound(int value)
1499 {
1500   if (value >= 1 && value <= MAX_INTEGER) {
1501     defaultBound_ = value;
1502   } else {
1503     handler_->message(COIN_MPS_ILLEGAL, messages_) << "default integer bound"
1504                                                    << value
1505                                                    << CoinMessageEol;
1506   }
1507 }
1508 // gets default upper bound for integer variables
getDefaultBound() const1509 int CoinMpsIO::getDefaultBound() const
1510 {
1511   return defaultBound_;
1512 }
1513 //------------------------------------------------------------------
1514 // Read mps files
1515 //------------------------------------------------------------------
readMps(const char * filename,const char * extension)1516 int CoinMpsIO::readMps(const char *filename, const char *extension)
1517 {
1518   // Deal with filename - +1 if new, 0 if same as before, -1 if error
1519 
1520   CoinFileInput *input = 0;
1521   int returnCode = dealWithFileName(filename, extension, input);
1522   if (returnCode < 0) {
1523     return -1;
1524   } else if (returnCode > 0) {
1525     delete cardReader_;
1526     cardReader_ = new CoinMpsCardReader(input, this);
1527   }
1528   if (!extension || (strcmp(extension, "gms") && !strstr(filename, ".gms"))) {
1529     return readMps();
1530   } else {
1531     int numberSets = 0;
1532     CoinSet **sets = NULL;
1533     int returnCode = readGms(numberSets, sets);
1534     for (int i = 0; i < numberSets; i++)
1535       delete sets[i];
1536     delete[] sets;
1537     return returnCode;
1538   }
1539 }
readMps(const char * filename,const char * extension,int & numberSets,CoinSet ** & sets)1540 int CoinMpsIO::readMps(const char *filename, const char *extension,
1541   int &numberSets, CoinSet **&sets)
1542 {
1543   // Deal with filename - +1 if new, 0 if same as before, -1 if error
1544   CoinFileInput *input = 0;
1545   int returnCode = dealWithFileName(filename, extension, input);
1546   if (returnCode < 0) {
1547     return -1;
1548   } else if (returnCode > 0) {
1549     delete cardReader_;
1550     cardReader_ = new CoinMpsCardReader(input, this);
1551   }
1552   return readMps(numberSets, sets);
1553 }
readMps()1554 int CoinMpsIO::readMps()
1555 {
1556   int numberSets = 0;
1557   CoinSet **sets = NULL;
1558   int returnCode = readMps(numberSets, sets);
1559   for (int i = 0; i < numberSets; i++)
1560     delete sets[i];
1561   delete[] sets;
1562   return returnCode;
1563 }
readMps(int & numberSets,CoinSet ** & sets)1564 int CoinMpsIO::readMps(int &numberSets, CoinSet **&sets)
1565 {
1566   bool ifmps;
1567 
1568   cardReader_->readToNextSection();
1569 
1570   if (cardReader_->whichSection() == COIN_NAME_SECTION) {
1571     ifmps = true;
1572     // save name of section
1573     free(problemName_);
1574     problemName_ = CoinStrdup(cardReader_->columnName());
1575   } else if (cardReader_->whichSection() == COIN_UNKNOWN_SECTION) {
1576     handler_->message(COIN_MPS_BADFILE1, messages_) << cardReader_->card()
1577                                                     << 1
1578                                                     << fileName_
1579                                                     << CoinMessageEol;
1580 
1581     if (cardReader_->fileInput()->getReadType() != "plain")
1582       handler_->message(COIN_MPS_BADFILE2, messages_)
1583         << cardReader_->fileInput()->getReadType()
1584         << CoinMessageEol;
1585 
1586     return -2;
1587   } else if (cardReader_->whichSection() != COIN_EOF_SECTION) {
1588     // save name of section
1589     free(problemName_);
1590     problemName_ = CoinStrdup(cardReader_->card());
1591     ifmps = false;
1592   } else {
1593     handler_->message(COIN_MPS_EOF, messages_) << fileName_
1594                                                << CoinMessageEol;
1595     return -3;
1596   }
1597   CoinBigIndex *start;
1598   COINRowIndex *row;
1599   double *element;
1600   objectiveOffset_ = 0.0;
1601 
1602   int numberErrors = 0;
1603   int i;
1604   if (ifmps) {
1605     // mps file - always read in free format
1606     bool gotNrow = false;
1607     // allow strings ?
1608     if (allowStringElements_)
1609       cardReader_->setStringsAllowed();
1610 
1611     //get ROWS
1612     cardReader_->nextField();
1613     // Fudge for what ever code has OBJSENSE
1614     if (!strncmp(cardReader_->card(), "OBJSENSE", 8)) {
1615       cardReader_->nextField();
1616       int i;
1617       const char *thisCard = cardReader_->card();
1618       int direction = 0;
1619       for (i = 0; i < 20; i++) {
1620         if (thisCard[i] != ' ') {
1621           if (!strncmp(thisCard + i, "MAX", 3))
1622             direction = -1;
1623           else if (!strncmp(thisCard + i, "MIN", 3))
1624             direction = 1;
1625           break;
1626         }
1627       }
1628       if (!direction)
1629         printf("No MAX/MIN found after OBJSENSE\n");
1630       else
1631         printf("%s found after OBJSENSE - Coin ignores\n",
1632           (direction > 0 ? "MIN" : "MAX"));
1633       cardReader_->nextField();
1634     }
1635     if (cardReader_->whichSection() != COIN_ROW_SECTION) {
1636       handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
1637                                                       << cardReader_->card()
1638                                                       << CoinMessageEol;
1639       handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1640       return numberErrors + 100000;
1641     }
1642     //use malloc etc as I don't know how to do realloc in C++
1643     numberRows_ = 0;
1644     numberColumns_ = 0;
1645     numberElements_ = 0;
1646     COINRowIndex maxRows = 1000;
1647     COINMpsType *rowType =
1648 
1649       reinterpret_cast< COINMpsType * >(malloc(maxRows * sizeof(COINMpsType)));
1650     char **rowName = reinterpret_cast< char ** >(malloc(maxRows * sizeof(char *)));
1651 
1652     // for discarded free rows
1653     COINRowIndex maxFreeRows = 100;
1654     COINRowIndex numberOtherFreeRows = 0;
1655     char **freeRowName =
1656 
1657       reinterpret_cast< char ** >(malloc(maxFreeRows * sizeof(char *)));
1658     while (cardReader_->nextField() == COIN_ROW_SECTION) {
1659       switch (cardReader_->mpsType()) {
1660       case COIN_N_ROW:
1661         if (!gotNrow) {
1662           gotNrow = true;
1663           // save name of section
1664           free(objectiveName_);
1665           objectiveName_ = CoinStrdup(cardReader_->columnName());
1666         } else {
1667           // add to discard list
1668           if (numberOtherFreeRows == maxFreeRows) {
1669             maxFreeRows = (3 * maxFreeRows) / 2 + 100;
1670             freeRowName = reinterpret_cast< char ** >(realloc(freeRowName,
1671               maxFreeRows * sizeof(char *)));
1672           }
1673           freeRowName[numberOtherFreeRows] = CoinStrdup(cardReader_->columnName());
1674           numberOtherFreeRows++;
1675         }
1676         break;
1677       case COIN_E_ROW:
1678       case COIN_L_ROW:
1679       case COIN_G_ROW:
1680         if (numberRows_ == maxRows) {
1681           maxRows = (3 * maxRows) / 2 + 1000;
1682           rowType = reinterpret_cast< COINMpsType * >(realloc(rowType,
1683             maxRows * sizeof(COINMpsType)));
1684           rowName =
1685 
1686             reinterpret_cast< char ** >(realloc(rowName, maxRows * sizeof(char *)));
1687         }
1688         rowType[numberRows_] = cardReader_->mpsType();
1689 #ifndef NONAMES
1690         rowName[numberRows_] = CoinStrdup(cardReader_->columnName());
1691 #endif
1692         numberRows_++;
1693         break;
1694       default:
1695         numberErrors++;
1696         if (numberErrors < 100) {
1697           handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
1698                                                           << cardReader_->card()
1699                                                           << CoinMessageEol;
1700         } else if (numberErrors > 100000) {
1701           handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1702           return numberErrors;
1703         }
1704       }
1705     }
1706     if (cardReader_->whichSection() != COIN_COLUMN_SECTION) {
1707       handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
1708                                                       << cardReader_->card()
1709                                                       << CoinMessageEol;
1710       handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1711       return numberErrors + 100000;
1712     }
1713     //assert ( gotNrow );
1714     if (numberRows_)
1715       rowType = reinterpret_cast< COINMpsType * >(realloc(rowType,
1716         numberRows_ * sizeof(COINMpsType)));
1717     else
1718       rowType = reinterpret_cast< COINMpsType * >(realloc(rowType, sizeof(COINMpsType)));
1719     // put objective and other free rows at end
1720     rowName = reinterpret_cast< char ** >(realloc(rowName,
1721       (numberRows_ + 1 +
1722 
1723         numberOtherFreeRows)
1724         * sizeof(char *)));
1725 #ifndef NONAMES
1726     rowName[numberRows_] = CoinStrdup(objectiveName_);
1727     memcpy(rowName + numberRows_ + 1, freeRowName,
1728       numberOtherFreeRows * sizeof(char *));
1729     // now we can get rid of this array
1730     free(freeRowName);
1731 #else
1732     memset(rowName, 0, (numberRows_ + 1) * sizeof(char **));
1733 #endif
1734 
1735     startHash(rowName, numberRows_ + 1 + numberOtherFreeRows, 0);
1736     COINColumnIndex maxColumns = 1000 + numberRows_ / 5;
1737     CoinBigIndex maxElements = 5000 + numberRows_ / 2;
1738     COINMpsType *columnType = reinterpret_cast< COINMpsType * >(malloc(maxColumns * sizeof(COINMpsType)));
1739     char **columnName = reinterpret_cast< char ** >(malloc(maxColumns * sizeof(char *)));
1740 
1741     objective_ = reinterpret_cast< double * >(malloc(maxColumns * sizeof(double)));
1742     start = reinterpret_cast< CoinBigIndex * >(malloc((maxColumns + 1) * sizeof(CoinBigIndex)));
1743     row = reinterpret_cast< COINRowIndex * >(malloc(maxElements * sizeof(COINRowIndex)));
1744     element = reinterpret_cast< double * >(malloc(maxElements * sizeof(double)));
1745     // for duplicates
1746     CoinBigIndex *rowUsed = new CoinBigIndex[numberRows_];
1747 
1748     for (i = 0; i < numberRows_; i++) {
1749       rowUsed[i] = -1;
1750     }
1751     bool objUsed = false;
1752 
1753     numberElements_ = 0;
1754     char lastColumn[200];
1755 
1756     memset(lastColumn, '\0', 200);
1757     COINColumnIndex column = -1;
1758     bool inIntegerSet = false;
1759     COINColumnIndex numberIntegers = 0;
1760 
1761     while (cardReader_->nextField() == COIN_COLUMN_SECTION) {
1762       switch (cardReader_->mpsType()) {
1763       case COIN_BLANK_COLUMN:
1764         if (strcmp(lastColumn, cardReader_->columnName())) {
1765           // new column
1766 
1767           // reset old column and take out tiny
1768           if (numberColumns_) {
1769             objUsed = false;
1770             CoinBigIndex i;
1771             CoinBigIndex k = start[column];
1772 
1773             for (i = k; i < numberElements_; i++) {
1774               COINRowIndex irow = row[i];
1775 #if 0
1776 	      if ( fabs ( element[i] ) > smallElement_ ) {
1777 		element[k++] = element[i];
1778 	      }
1779 #endif
1780               rowUsed[irow] = -1;
1781             }
1782             //numberElements_ = k;
1783           }
1784           column = numberColumns_;
1785           if (numberColumns_ == maxColumns) {
1786             maxColumns = (3 * maxColumns) / 2 + 1000;
1787             columnType = reinterpret_cast< COINMpsType * >(realloc(columnType, maxColumns * sizeof(COINMpsType)));
1788             columnName = reinterpret_cast< char ** >(realloc(columnName, maxColumns * sizeof(char *)));
1789 
1790             objective_ = reinterpret_cast< double * >(realloc(objective_, maxColumns * sizeof(double)));
1791             start = reinterpret_cast< CoinBigIndex * >(realloc(start,
1792               (maxColumns + 1) * sizeof(CoinBigIndex)));
1793           }
1794           if (!inIntegerSet) {
1795             columnType[column] = COIN_UNSET_BOUND;
1796           } else {
1797             columnType[column] = COIN_INTORG;
1798             numberIntegers++;
1799           }
1800 #ifndef NONAMES
1801           columnName[column] = CoinStrdup(cardReader_->columnName());
1802 #else
1803           columnName[column] = NULL;
1804 #endif
1805           strcpy(lastColumn, cardReader_->columnName());
1806           objective_[column] = 0.0;
1807           start[column] = numberElements_;
1808           numberColumns_++;
1809         }
1810         if (fabs(cardReader_->value()) > smallElement_) {
1811           if (numberElements_ == maxElements) {
1812             maxElements = (3 * maxElements) / 2 + 1000;
1813             row = reinterpret_cast< COINRowIndex * >(realloc(row, maxElements * sizeof(COINRowIndex)));
1814             element = reinterpret_cast< double * >(realloc(element, maxElements * sizeof(double)));
1815           }
1816           // get row number
1817           COINRowIndex irow = findHash(cardReader_->rowName(), 0);
1818 
1819           if (irow >= 0) {
1820             double value = cardReader_->value();
1821 
1822             // check for duplicates
1823             if (irow == numberRows_) {
1824               // objective
1825               if (objUsed) {
1826                 numberErrors++;
1827                 if (numberErrors < 100) {
1828                   handler_->message(COIN_MPS_DUPOBJ, messages_)
1829                     << cardReader_->cardNumber() << cardReader_->card()
1830                     << CoinMessageEol;
1831                 } else if (numberErrors > 100000) {
1832                   handler_->message(COIN_MPS_RETURNING, messages_)
1833                     << CoinMessageEol;
1834                   return numberErrors;
1835                 }
1836               } else {
1837                 objUsed = true;
1838               }
1839               value += objective_[column];
1840               if (fabs(value) <= smallElement_)
1841                 value = 0.0;
1842               objective_[column] = value;
1843             } else if (irow < numberRows_) {
1844               // other free rows will just be discarded so won't get here
1845               if (rowUsed[irow] >= 0) {
1846                 element[rowUsed[irow]] += value;
1847                 numberErrors++;
1848                 if (numberErrors < 100) {
1849                   handler_->message(COIN_MPS_DUPROW, messages_)
1850                     << cardReader_->rowName() << cardReader_->cardNumber()
1851                     << cardReader_->card()
1852                     << CoinMessageEol;
1853                 } else if (numberErrors > 100000) {
1854                   handler_->message(COIN_MPS_RETURNING, messages_)
1855                     << CoinMessageEol;
1856                   return numberErrors;
1857                 }
1858               } else {
1859                 row[numberElements_] = irow;
1860                 element[numberElements_] = value;
1861                 rowUsed[irow] = numberElements_;
1862                 numberElements_++;
1863               }
1864             }
1865           } else {
1866             numberErrors++;
1867             if (numberErrors < 100) {
1868               handler_->message(COIN_MPS_NOMATCHROW, messages_)
1869                 << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
1870                 << CoinMessageEol;
1871             } else if (numberErrors > 100000) {
1872               handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1873               return numberErrors;
1874             }
1875           }
1876         } else if (cardReader_->value() == STRING_VALUE) {
1877           // tiny element - string
1878           const char *s = cardReader_->valueString();
1879           assert(*s == '=');
1880           // get row number
1881           COINRowIndex irow = findHash(cardReader_->rowName(), 0);
1882 
1883           if (irow >= 0) {
1884             addString(irow, column, s + 1);
1885           } else {
1886             numberErrors++;
1887             if (numberErrors < 100) {
1888               handler_->message(COIN_MPS_NOMATCHROW, messages_)
1889                 << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
1890                 << CoinMessageEol;
1891             } else if (numberErrors > 100000) {
1892               handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1893               return numberErrors;
1894             }
1895           }
1896         }
1897         break;
1898       case COIN_INTORG:
1899         inIntegerSet = true;
1900         break;
1901       case COIN_INTEND:
1902         inIntegerSet = false;
1903         break;
1904       case COIN_S1_COLUMN:
1905       case COIN_S2_COLUMN:
1906       case COIN_S3_COLUMN:
1907       case COIN_SOSEND:
1908         std::cout << "** code sos etc later" << std::endl;
1909         abort();
1910         break;
1911       default:
1912         numberErrors++;
1913         if (numberErrors < 100) {
1914           handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
1915                                                           << cardReader_->card()
1916                                                           << CoinMessageEol;
1917         } else if (numberErrors > 100000) {
1918           handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1919           return numberErrors;
1920         }
1921       }
1922     }
1923     start[numberColumns_] = numberElements_;
1924     delete[] rowUsed;
1925     if (cardReader_->whichSection() != COIN_RHS_SECTION) {
1926       handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
1927                                                       << cardReader_->card()
1928                                                       << CoinMessageEol;
1929       handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
1930       return numberErrors + 100000;
1931     }
1932     if (numberColumns_) {
1933       columnType = reinterpret_cast< COINMpsType * >(realloc(columnType,
1934         numberColumns_ * sizeof(COINMpsType)));
1935       columnName =
1936 
1937         reinterpret_cast< char ** >(realloc(columnName, numberColumns_ * sizeof(char *)));
1938       objective_ = reinterpret_cast< double * >(realloc(objective_, numberColumns_ * sizeof(double)));
1939     } else {
1940       columnType = reinterpret_cast< COINMpsType * >(realloc(columnType,
1941         sizeof(COINMpsType)));
1942       columnName =
1943 
1944         reinterpret_cast< char ** >(realloc(columnName, sizeof(char *)));
1945       objective_ = reinterpret_cast< double * >(realloc(objective_, sizeof(double)));
1946     }
1947     start = reinterpret_cast< CoinBigIndex * >(realloc(start, (numberColumns_ + 1) * sizeof(CoinBigIndex)));
1948     if (numberElements_) {
1949       row = reinterpret_cast< COINRowIndex * >(realloc(row, numberElements_ * sizeof(COINRowIndex)));
1950       element = reinterpret_cast< double * >(realloc(element, numberElements_ * sizeof(double)));
1951     } else {
1952       row = reinterpret_cast< COINRowIndex * >(realloc(row, sizeof(COINRowIndex)));
1953       element = reinterpret_cast< double * >(realloc(element, sizeof(double)));
1954     }
1955     if (numberRows_) {
1956       rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
1957       rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
1958     } else {
1959       rowlower_ = reinterpret_cast< double * >(malloc(sizeof(double)));
1960       rowupper_ = reinterpret_cast< double * >(malloc(sizeof(double)));
1961     }
1962     for (i = 0; i < numberRows_; i++) {
1963       rowlower_[i] = -infinity_;
1964       rowupper_[i] = infinity_;
1965     }
1966     objUsed = false;
1967     memset(lastColumn, '\0', 200);
1968     bool gotRhs = false;
1969 
1970     // need coding for blank rhs
1971     while (cardReader_->nextField() == COIN_RHS_SECTION) {
1972       COINRowIndex irow;
1973 
1974       switch (cardReader_->mpsType()) {
1975       case COIN_BLANK_COLUMN:
1976         if (strcmp(lastColumn, cardReader_->columnName())) {
1977 
1978           // skip rest if got a rhs
1979           if (gotRhs) {
1980             while (cardReader_->nextField() == COIN_RHS_SECTION) {
1981             }
1982             break;
1983           } else {
1984             gotRhs = true;
1985             strcpy(lastColumn, cardReader_->columnName());
1986             // save name of section
1987             free(rhsName_);
1988             rhsName_ = CoinStrdup(cardReader_->columnName());
1989           }
1990         }
1991         // get row number
1992         irow = findHash(cardReader_->rowName(), 0);
1993         if (irow >= 0) {
1994           double value = cardReader_->value();
1995 
1996           // check for duplicates
1997           if (irow == numberRows_) {
1998             // objective
1999             if (objUsed) {
2000               numberErrors++;
2001               if (numberErrors < 100) {
2002                 handler_->message(COIN_MPS_DUPOBJ, messages_)
2003                   << cardReader_->cardNumber() << cardReader_->card()
2004                   << CoinMessageEol;
2005               } else if (numberErrors > 100000) {
2006                 handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2007                 return numberErrors;
2008               }
2009             } else {
2010               objUsed = true;
2011             }
2012             if (value == STRING_VALUE) {
2013               value = 0.0;
2014               // tiny element - string
2015               const char *s = cardReader_->valueString();
2016               assert(*s == '=');
2017               addString(irow, numberColumns_, s + 1);
2018             }
2019             objectiveOffset_ += value;
2020           } else if (irow < numberRows_) {
2021             if (rowlower_[irow] != -infinity_) {
2022               numberErrors++;
2023               if (numberErrors < 100) {
2024                 handler_->message(COIN_MPS_DUPROW, messages_)
2025                   << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
2026                   << CoinMessageEol;
2027               } else if (numberErrors > 100000) {
2028                 handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2029                 return numberErrors;
2030               }
2031             } else {
2032               if (value == STRING_VALUE) {
2033                 value = 0.0;
2034                 // tiny element - string
2035                 const char *s = cardReader_->valueString();
2036                 assert(*s == '=');
2037                 addString(irow, numberColumns_, s + 1);
2038               }
2039               rowlower_[irow] = value;
2040             }
2041           }
2042         } else {
2043           numberErrors++;
2044           if (numberErrors < 100) {
2045             handler_->message(COIN_MPS_NOMATCHROW, messages_)
2046               << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
2047               << CoinMessageEol;
2048           } else if (numberErrors > 100000) {
2049             handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2050             return numberErrors;
2051           }
2052         }
2053         break;
2054       default:
2055         numberErrors++;
2056         if (numberErrors < 100) {
2057           handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
2058                                                           << cardReader_->card()
2059                                                           << CoinMessageEol;
2060         } else if (numberErrors > 100000) {
2061           handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2062           return numberErrors;
2063         }
2064       }
2065     }
2066     if (cardReader_->whichSection() == COIN_RANGES_SECTION) {
2067       memset(lastColumn, '\0', 200);
2068       bool gotRange = false;
2069       COINRowIndex irow;
2070 
2071       // need coding for blank range
2072       while (cardReader_->nextField() == COIN_RANGES_SECTION) {
2073         switch (cardReader_->mpsType()) {
2074         case COIN_BLANK_COLUMN:
2075           if (strcmp(lastColumn, cardReader_->columnName())) {
2076 
2077             // skip rest if got a range
2078             if (gotRange) {
2079               while (cardReader_->nextField() == COIN_RANGES_SECTION) {
2080               }
2081               break;
2082             } else {
2083               gotRange = true;
2084               strcpy(lastColumn, cardReader_->columnName());
2085               // save name of section
2086               free(rangeName_);
2087               rangeName_ = CoinStrdup(cardReader_->columnName());
2088             }
2089           }
2090           // get row number
2091           irow = findHash(cardReader_->rowName(), 0);
2092           if (irow >= 0) {
2093             double value = cardReader_->value();
2094 
2095             // check for duplicates
2096             if (irow == numberRows_) {
2097               // objective
2098               numberErrors++;
2099               if (numberErrors < 100) {
2100                 handler_->message(COIN_MPS_DUPOBJ, messages_)
2101                   << cardReader_->cardNumber() << cardReader_->card()
2102                   << CoinMessageEol;
2103               } else if (numberErrors > 100000) {
2104                 handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2105                 return numberErrors;
2106               }
2107             } else {
2108               if (rowupper_[irow] != infinity_) {
2109                 numberErrors++;
2110                 if (numberErrors < 100) {
2111                   handler_->message(COIN_MPS_DUPROW, messages_)
2112                     << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
2113                     << CoinMessageEol;
2114                 } else if (numberErrors > 100000) {
2115                   handler_->message(COIN_MPS_RETURNING, messages_)
2116                     << CoinMessageEol;
2117                   return numberErrors;
2118                 }
2119               } else {
2120                 rowupper_[irow] = value;
2121               }
2122             }
2123           } else {
2124             numberErrors++;
2125             if (numberErrors < 100) {
2126               handler_->message(COIN_MPS_NOMATCHROW, messages_)
2127                 << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
2128                 << CoinMessageEol;
2129             } else if (numberErrors > 100000) {
2130               handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2131               return numberErrors;
2132             }
2133           }
2134           break;
2135         default:
2136           numberErrors++;
2137           if (numberErrors < 100) {
2138             handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
2139                                                             << cardReader_->card()
2140                                                             << CoinMessageEol;
2141           } else if (numberErrors > 100000) {
2142             handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2143             return numberErrors;
2144           }
2145         }
2146       }
2147     }
2148     stopHash(0);
2149     // massage ranges
2150     {
2151       COINRowIndex irow;
2152 
2153       for (irow = 0; irow < numberRows_; irow++) {
2154         double lo = rowlower_[irow];
2155         double up = rowupper_[irow];
2156         double up2 = rowupper_[irow]; //range
2157 
2158         switch (rowType[irow]) {
2159         case COIN_E_ROW:
2160           if (lo == -infinity_)
2161             lo = 0.0;
2162           if (up == infinity_) {
2163             up = lo;
2164           } else if (up > 0.0) {
2165             up += lo;
2166           } else {
2167             up = lo;
2168             lo += up2;
2169           }
2170           break;
2171         case COIN_L_ROW:
2172           if (lo == -infinity_) {
2173             up = 0.0;
2174           } else {
2175             up = lo;
2176             lo = -infinity_;
2177           }
2178           if (up2 != infinity_) {
2179             lo = up - fabs(up2);
2180           }
2181           break;
2182         case COIN_G_ROW:
2183           if (lo == -infinity_) {
2184             lo = 0.0;
2185             up = infinity_;
2186           } else {
2187             up = infinity_;
2188           }
2189           if (up2 != infinity_) {
2190             up = lo + fabs(up2);
2191           }
2192           break;
2193         default:
2194           abort();
2195         }
2196         rowlower_[irow] = lo;
2197         rowupper_[irow] = up;
2198       }
2199     }
2200     free(rowType);
2201     // default bounds
2202     if (numberColumns_) {
2203       collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2204       colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2205     } else {
2206       collower_ = reinterpret_cast< double * >(malloc(sizeof(double)));
2207       colupper_ = reinterpret_cast< double * >(malloc(sizeof(double)));
2208     }
2209     for (i = 0; i < numberColumns_; i++) {
2210       collower_[i] = 0.0;
2211       colupper_[i] = infinity_;
2212     }
2213     // set up integer region just in case
2214     if (numberColumns_)
2215       integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
2216     else
2217       integerType_ = reinterpret_cast< char * >(malloc(sizeof(char)));
2218     for (column = 0; column < numberColumns_; column++) {
2219       if (columnType[column] == COIN_INTORG) {
2220         columnType[column] = COIN_UNSET_BOUND;
2221         integerType_[column] = 1;
2222       } else {
2223         integerType_[column] = 0;
2224       }
2225     }
2226     // start hash even if no bound section - to make sure names survive
2227     startHash(columnName, numberColumns_, 1);
2228     if (cardReader_->whichSection() == COIN_BOUNDS_SECTION) {
2229       memset(lastColumn, '\0', 200);
2230       bool gotBound = false;
2231 
2232       while (cardReader_->nextField() == COIN_BOUNDS_SECTION) {
2233         if (strcmp(lastColumn, cardReader_->columnName())) {
2234 
2235           // skip rest if got a bound
2236           if (gotBound) {
2237             while (cardReader_->nextField() == COIN_BOUNDS_SECTION) {
2238             }
2239             break;
2240           } else {
2241             gotBound = true;
2242             ;
2243             strcpy(lastColumn, cardReader_->columnName());
2244             // save name of section
2245             free(boundName_);
2246             boundName_ = CoinStrdup(cardReader_->columnName());
2247           }
2248         }
2249         // get column number
2250         COINColumnIndex icolumn = findHash(cardReader_->rowName(), 1);
2251 
2252         if (icolumn >= 0) {
2253           double value = cardReader_->value();
2254           bool ifError = false;
2255 
2256           switch (cardReader_->mpsType()) {
2257           case COIN_UP_BOUND:
2258             if (value == -1.0e100)
2259               ifError = true;
2260             if (value == STRING_VALUE) {
2261               value = 1.0e10;
2262               // tiny element - string
2263               const char *s = cardReader_->valueString();
2264               assert(*s == '=');
2265               addString(numberRows_ + 2, icolumn, s + 1);
2266             }
2267             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2268               if (value < 0.0) {
2269                 collower_[icolumn] = -infinity_;
2270               }
2271             } else if (columnType[icolumn] == COIN_LO_BOUND || columnType[icolumn] == COIN_LI_BOUND) {
2272               if (value < collower_[icolumn]) {
2273                 ifError = true;
2274               } else if (value < collower_[icolumn] + smallElement_) {
2275                 value = collower_[icolumn];
2276               }
2277             } else if (columnType[icolumn] == COIN_MI_BOUND) {
2278             } else {
2279               ifError = true;
2280             }
2281             if (value > 1.0e25)
2282               value = infinity_;
2283             colupper_[icolumn] = value;
2284             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2285               columnType[icolumn] = COIN_UP_BOUND;
2286             } else {
2287               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2288             }
2289             break;
2290           case COIN_LO_BOUND:
2291             if (value == -1.0e100)
2292               ifError = true;
2293             if (value == STRING_VALUE) {
2294               value = -1.0e10;
2295               // tiny element - string
2296               const char *s = cardReader_->valueString();
2297               assert(*s == '=');
2298               addString(numberRows_ + 1, icolumn, s + 1);
2299             }
2300             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2301             } else if (columnType[icolumn] == COIN_UP_BOUND || columnType[icolumn] == COIN_SC_BOUND || columnType[icolumn] == COIN_UI_BOUND) {
2302               if (value > colupper_[icolumn]) {
2303                 ifError = true;
2304               } else if (value > colupper_[icolumn] - smallElement_) {
2305                 value = colupper_[icolumn];
2306               }
2307             } else if (columnType[icolumn] == COIN_PL_BOUND) {
2308             } else {
2309               ifError = true;
2310             }
2311             if (value < -1.0e25)
2312               value = -infinity_;
2313             collower_[icolumn] = value;
2314             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2315               columnType[icolumn] = COIN_LO_BOUND;
2316             } else {
2317               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2318             }
2319             break;
2320           case COIN_FX_BOUND:
2321             if (value == -1.0e100)
2322               ifError = true;
2323             if (value == STRING_VALUE) {
2324               value = 0.0;
2325               // tiny element - string
2326               const char *s = cardReader_->valueString();
2327               assert(*s == '=');
2328               addString(numberRows_ + 1, icolumn, s + 1);
2329               addString(numberRows_ + 2, icolumn, s + 1);
2330             }
2331             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2332             } else if (columnType[icolumn] == COIN_FX_BOUND) {
2333               ifError = true;
2334             } else if (integerType_[icolumn]) {
2335               // Allow so people can easily put FX's at end
2336               double value2 = floor(value);
2337               if (fabs(value2 - value) > 1.0e-12 || value2 < collower_[icolumn] || value2 > colupper_[icolumn]) {
2338                 ifError = true;
2339               } else {
2340                 // take off integer list
2341                 numberIntegers--;
2342                 integerType_[icolumn] = 0;
2343               }
2344             } else {
2345               ifError = true;
2346             }
2347             collower_[icolumn] = value;
2348             colupper_[icolumn] = value;
2349             columnType[icolumn] = COIN_FX_BOUND;
2350             break;
2351           case COIN_FR_BOUND:
2352             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2353             } else {
2354               ifError = true;
2355             }
2356             collower_[icolumn] = -infinity_;
2357             colupper_[icolumn] = infinity_;
2358             columnType[icolumn] = COIN_FR_BOUND;
2359             break;
2360           case COIN_MI_BOUND:
2361             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2362               colupper_[icolumn] = COIN_DBL_MAX;
2363             } else if (columnType[icolumn] == COIN_UP_BOUND || columnType[icolumn] == COIN_UI_BOUND) {
2364             } else {
2365               ifError = true;
2366             }
2367             collower_[icolumn] = -infinity_;
2368             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2369               columnType[icolumn] = COIN_MI_BOUND;
2370             } else {
2371               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2372             }
2373             break;
2374           case COIN_PL_BOUND:
2375             // change to allow if no upper bound set
2376             //if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
2377             if (colupper_[icolumn] == infinity_) {
2378             } else {
2379               ifError = true;
2380             }
2381             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2382               columnType[icolumn] = COIN_PL_BOUND;
2383             } else {
2384               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2385             }
2386             break;
2387           case COIN_UI_BOUND:
2388             if (value == STRING_VALUE) {
2389               value = 1.0e20;
2390               // tiny element - string
2391               const char *s = cardReader_->valueString();
2392               assert(*s == '=');
2393               addString(numberRows_ + 2, icolumn, s + 1);
2394             }
2395 #if 0
2396 	    if ( value == -1.0e100 )
2397 	      ifError = true;
2398 	    if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
2399 	    } else if ( columnType[icolumn] == COIN_LO_BOUND ||
2400                         columnType[icolumn] == COIN_LI_BOUND) {
2401 	      if ( value < collower_[icolumn] ) {
2402 		ifError = true;
2403 	      } else if ( value < collower_[icolumn] + smallElement_ ) {
2404 		value = collower_[icolumn];
2405 	      }
2406 	    } else if ( columnType[icolumn] == COIN_MI_BOUND ) {
2407 	    } else {
2408 	      ifError = true;
2409 	    }
2410 #else
2411             if (value == -1.0e100) {
2412               value = infinity_;
2413               if (columnType[icolumn] != COIN_UNSET_BOUND && columnType[icolumn] != COIN_LO_BOUND && columnType[icolumn] != COIN_LI_BOUND && columnType[icolumn] != COIN_MI_BOUND) {
2414                 ifError = true;
2415               }
2416             } else {
2417               if (columnType[icolumn] == COIN_UNSET_BOUND) {
2418               } else if (columnType[icolumn] == COIN_LO_BOUND || columnType[icolumn] == COIN_LI_BOUND || columnType[icolumn] == COIN_MI_BOUND) {
2419                 if (value < collower_[icolumn]) {
2420                   ifError = true;
2421                 } else if (value < collower_[icolumn] + smallElement_) {
2422                   value = collower_[icolumn];
2423                 }
2424               } else {
2425                 ifError = true;
2426               }
2427             }
2428 #endif
2429             if (value > 1.0e25)
2430               value = infinity_;
2431             colupper_[icolumn] = value;
2432             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2433               columnType[icolumn] = COIN_UI_BOUND;
2434             } else {
2435               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2436             }
2437             if (!integerType_[icolumn]) {
2438               numberIntegers++;
2439               integerType_[icolumn] = 1;
2440             }
2441             break;
2442           case COIN_LI_BOUND:
2443             if (value == -1.0e100)
2444               ifError = true;
2445             if (value == STRING_VALUE) {
2446               value = -1.0e20;
2447               // tiny element - string
2448               const char *s = cardReader_->valueString();
2449               assert(*s == '=');
2450               addString(numberRows_ + 1, icolumn, s + 1);
2451             }
2452             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2453             } else if (columnType[icolumn] == COIN_UP_BOUND || columnType[icolumn] == COIN_SC_BOUND || columnType[icolumn] == COIN_UI_BOUND) {
2454               if (value > colupper_[icolumn]) {
2455                 ifError = true;
2456               } else if (value > colupper_[icolumn] - smallElement_) {
2457                 value = colupper_[icolumn];
2458               }
2459             } else if (columnType[icolumn] == COIN_PL_BOUND) {
2460             } else {
2461               ifError = true;
2462             }
2463             if (value < -1.0e25)
2464               value = -infinity_;
2465             collower_[icolumn] = value;
2466             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2467               columnType[icolumn] = COIN_LI_BOUND;
2468             } else {
2469               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2470             }
2471             if (!integerType_[icolumn]) {
2472               numberIntegers++;
2473               integerType_[icolumn] = 1;
2474             } else if (integerType_[icolumn] == 3) {
2475               integerType_[icolumn] = 4; // SC and integer
2476             }
2477             break;
2478           case COIN_BV_BOUND:
2479             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2480             } else {
2481               ifError = true;
2482             }
2483             collower_[icolumn] = 0.0;
2484             colupper_[icolumn] = 1.0;
2485             columnType[icolumn] = COIN_BV_BOUND;
2486             if (!integerType_[icolumn]) {
2487               numberIntegers++;
2488               integerType_[icolumn] = 1;
2489             }
2490             break;
2491           case COIN_SC_BOUND:
2492             if (value == STRING_VALUE) {
2493               value = 1.0e20;
2494               // tiny element - string
2495               const char *s = cardReader_->valueString();
2496               assert(*s == '=');
2497               addString(numberRows_ + 2, icolumn, s + 1);
2498             }
2499             if (value == -1.0e100 || value == 0.0) {
2500               value = infinity_;
2501               if (columnType[icolumn] != COIN_UNSET_BOUND && columnType[icolumn] != COIN_LO_BOUND && columnType[icolumn] != COIN_LI_BOUND) {
2502                 ifError = true;
2503               }
2504             } else {
2505               if (columnType[icolumn] == COIN_UNSET_BOUND) {
2506               } else if (columnType[icolumn] == COIN_LO_BOUND || columnType[icolumn] == COIN_LI_BOUND) {
2507                 if (value < collower_[icolumn]) {
2508                   ifError = true;
2509                 } else if (value < collower_[icolumn] + smallElement_) {
2510                   value = collower_[icolumn];
2511                 }
2512               } else {
2513                 ifError = true;
2514               }
2515             }
2516             if (value > 1.0e25)
2517               value = infinity_;
2518             colupper_[icolumn] = value;
2519             if (columnType[icolumn] == COIN_UNSET_BOUND) {
2520               columnType[icolumn] = COIN_SC_BOUND;
2521             } else {
2522               columnType[icolumn] = COIN_BOTH_BOUNDS_SET;
2523             }
2524             if (!integerType_[icolumn]) {
2525               numberIntegers++;
2526               integerType_[icolumn] = 3;
2527             } else if (integerType_[icolumn] == 1) {
2528               integerType_[icolumn] = 4; // SC and integer
2529             }
2530             break;
2531           default:
2532             ifError = true;
2533             break;
2534           }
2535           if (ifError) {
2536             numberErrors++;
2537             if (numberErrors < 100) {
2538               handler_->message(COIN_MPS_BADIMAGE, messages_)
2539                 << cardReader_->cardNumber()
2540                 << cardReader_->card()
2541                 << CoinMessageEol;
2542             } else if (numberErrors > 100000) {
2543               handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2544               return numberErrors;
2545             }
2546           }
2547         } else {
2548           numberErrors++;
2549           if (numberErrors < 100) {
2550             handler_->message(COIN_MPS_NOMATCHCOL, messages_)
2551               << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
2552               << CoinMessageEol;
2553           } else if (numberErrors > 100000) {
2554             handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2555             return numberErrors;
2556           }
2557         }
2558       }
2559     }
2560     //for (i=0;i<numberSets;i++)
2561     //delete sets[i];
2562     numberSets = 0;
2563     //delete [] sets;
2564     sets = NULL;
2565 
2566     // Do SOS if found
2567     if (cardReader_->whichSection() == COIN_SOS_SECTION) {
2568       // Go to free format
2569       cardReader_->setFreeFormat(true);
2570       int numberInSet = 0;
2571       int iType = -1;
2572       int *which = new int[numberColumns_];
2573       double *weights = new double[numberColumns_];
2574       CoinSet **setsA = new CoinSet *[numberColumns_];
2575       while (cardReader_->nextField() == COIN_SOS_SECTION) {
2576         if (cardReader_->mpsType() == COIN_S1_BOUND || cardReader_->mpsType() == COIN_S2_BOUND) {
2577           if (numberInSet) {
2578             CoinSosSet *newSet = new CoinSosSet(numberInSet, which, weights, iType);
2579             setsA[numberSets++] = newSet;
2580           }
2581           numberInSet = 0;
2582           iType = cardReader_->mpsType() == COIN_S1_BOUND ? 1 : 2;
2583           // skip
2584           continue;
2585         }
2586         // get column number
2587         COINColumnIndex icolumn = findHash(cardReader_->columnName(), 1);
2588         if (icolumn >= 0) {
2589           //integerType_[icolumn]=2;
2590           double value = cardReader_->value();
2591           if (value == -1.0e100)
2592             value = atof(cardReader_->rowName()); // try from row name
2593           which[numberInSet] = icolumn;
2594           weights[numberInSet++] = value;
2595         } else {
2596           numberErrors++;
2597           if (numberErrors < 100) {
2598             handler_->message(COIN_MPS_NOMATCHCOL, messages_)
2599               << cardReader_->columnName() << cardReader_->cardNumber() << cardReader_->card()
2600               << CoinMessageEol;
2601           } else if (numberErrors > 100000) {
2602             handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2603             return numberErrors;
2604           }
2605         }
2606       }
2607       if (numberInSet) {
2608         CoinSosSet *newSet = new CoinSosSet(numberInSet, which, weights, iType);
2609         setsA[numberSets++] = newSet;
2610       }
2611       if (numberSets) {
2612         sets = new CoinSet *[numberSets];
2613         memcpy(sets, setsA, numberSets * sizeof(CoinSet **));
2614       }
2615       delete[] setsA;
2616       delete[] which;
2617       delete[] weights;
2618     }
2619     stopHash(1);
2620     // clean up integers
2621     if (!numberIntegers) {
2622       free(integerType_);
2623       integerType_ = NULL;
2624     } else {
2625       COINColumnIndex icolumn;
2626 
2627       for (icolumn = 0; icolumn < numberColumns_; icolumn++) {
2628         if (integerType_[icolumn]) {
2629           collower_[icolumn] = CoinMax(collower_[icolumn], -MAX_INTEGER);
2630           // if 0 infinity make 0-1 ???
2631           if (columnType[icolumn] == COIN_UNSET_BOUND)
2632             colupper_[icolumn] = defaultBound_;
2633           if (colupper_[icolumn] > MAX_INTEGER)
2634             colupper_[icolumn] = MAX_INTEGER;
2635           // clean up to allow for bad reads on 1.0e2 etc
2636           if (colupper_[icolumn] < 1.0e10) {
2637             double value = colupper_[icolumn];
2638             double value2 = floor(value + 0.5);
2639             if (value != value2) {
2640               if (fabs(value - value2) < 1.0e-5)
2641                 colupper_[icolumn] = value2;
2642             }
2643           }
2644           if (collower_[icolumn] > -1.0e10) {
2645             double value = collower_[icolumn];
2646             double value2 = floor(value + 0.5);
2647             if (value != value2) {
2648               if (fabs(value - value2) < 1.0e-5)
2649                 collower_[icolumn] = value2;
2650             }
2651           }
2652         }
2653       }
2654     }
2655     free(columnType);
2656     if (cardReader_->whichSection() != COIN_ENDATA_SECTION && cardReader_->whichSection() != COIN_QUAD_SECTION && cardReader_->whichSection() != COIN_CONIC_SECTION) {
2657       handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
2658                                                       << cardReader_->card()
2659                                                       << CoinMessageEol;
2660       handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
2661       return numberErrors + 100000;
2662     }
2663   } else {
2664     // This is very simple format - what should we use?
2665     COINColumnIndex i;
2666 
2667     /* old:
2668        FILE * fp = cardReader_->filePointer();
2669        fscanf ( fp, "%d %d %d\n", &numberRows_, &numberColumns_, &i);
2670     */
2671     // new:
2672     char buffer[1000];
2673     cardReader_->fileInput()->gets(buffer, 1000);
2674     sscanf(buffer, "%d %d %d\n", &numberRows_, &numberColumns_, &i);
2675 
2676     numberElements_ = i; // done this way in case numberElements_ long
2677 
2678     rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
2679     rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
2680     for (i = 0; i < numberRows_; i++) {
2681       int j;
2682 
2683       // old: fscanf ( fp, "%d %lg %lg\n", &j, &rowlower_[i], &rowupper_[i] );
2684       // new:
2685       cardReader_->fileInput()->gets(buffer, 1000);
2686       sscanf(buffer, "%d %lg %lg\n", &j, &rowlower_[i], &rowupper_[i]);
2687 
2688       assert(i == j);
2689     }
2690     collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2691     colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2692     objective_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2693     start = reinterpret_cast< CoinBigIndex * >(malloc((numberColumns_ + 1) * sizeof(CoinBigIndex)));
2694     row = reinterpret_cast< COINRowIndex * >(malloc(numberElements_ * sizeof(COINRowIndex)));
2695     element = reinterpret_cast< double * >(malloc(numberElements_ * sizeof(double)));
2696 
2697     start[0] = 0;
2698     numberElements_ = 0;
2699     for (i = 0; i < numberColumns_; i++) {
2700       int j;
2701       int n;
2702 
2703       /* old:
2704 	 fscanf ( fp, "%d %d %lg %lg %lg\n", &j, &n,
2705 	          &collower_[i], &colupper_[i],
2706 	          &objective_[i] );
2707       */
2708       // new:
2709       cardReader_->fileInput()->gets(buffer, 1000);
2710       sscanf(buffer, "%d %d %lg %lg %lg\n", &j, &n,
2711         &collower_[i], &colupper_[i], &objective_[i]);
2712 
2713       assert(i == j);
2714       for (j = 0; j < n; j++) {
2715         /* old:
2716 	   fscanf ( fp, "       %d %lg\n", &row[numberElements_],
2717 		 &element[numberElements_] );
2718 	*/
2719         // new:
2720         cardReader_->fileInput()->gets(buffer, 1000);
2721         sscanf(buffer, "       %d %lg\n", &row[numberElements_],
2722           &element[numberElements_]);
2723 
2724         numberElements_++;
2725       }
2726       start[i + 1] = numberElements_;
2727     }
2728   }
2729   // construct packed matrix
2730   matrixByColumn_ = new CoinPackedMatrix(true,
2731     numberRows_, numberColumns_, numberElements_,
2732     element, row, start, NULL);
2733   free(row);
2734   free(start);
2735   free(element);
2736 
2737   handler_->message(COIN_MPS_STATS, messages_) << problemName_
2738                                                << numberRows_
2739                                                << numberColumns_
2740                                                << numberElements_
2741                                                << CoinMessageEol;
2742 
2743   if (integerType_) {
2744     int numberSC = 0;
2745     int numberSC_int = 0;
2746     for (int i = 0; i < numberColumns_; i++) {
2747       if (integerType_[i] > 2 && integerType_[i] < 5)
2748         numberSC++;
2749       if (integerType_[i] == 4)
2750         numberSC_int++;
2751     }
2752     if (numberSC) {
2753       char generalPrint[100];
2754       if (!numberSC_int)
2755         sprintf(generalPrint, "%d semi-continuous variables - report odd behavior",
2756           numberSC);
2757       else
2758         sprintf(generalPrint, "%d semi-continuous variables (%d integer!) - be wary",
2759           numberSC, numberSC_int);
2760       handler_->message(COIN_GENERAL_INFO, messages_) << generalPrint << CoinMessageEol;
2761     }
2762   }
2763   return numberErrors;
2764 }
2765 #ifdef COIN_HAS_GLPK
2766 #include "glpk.h"
2767 glp_tran *cbc_glp_tran = NULL;
2768 glp_prob *cbc_glp_prob = NULL;
2769 #endif
2770 /* Read a problem in GMPL (subset of AMPL)  format from the given filenames.
2771    Thanks to Ted Ralphs - I just looked at his coding rather than look at the GMPL documentation.
2772  */
readGMPL(const char * modelName,const char * dataName,bool keepNames)2773 int CoinMpsIO::readGMPL(const char *modelName, const char *dataName,
2774   bool keepNames)
2775 {
2776 #ifdef COIN_HAS_GLPK
2777   int returnCode;
2778   gutsOfDestructor();
2779   // initialize
2780   cbc_glp_tran = glp_mpl_alloc_wksp();
2781   // read model
2782   char name[2000]; // should be long enough
2783   assert(strlen(modelName) < 2000 && (!dataName || strlen(dataName) < 2000));
2784   strcpy(name, modelName);
2785   returnCode = glp_mpl_read_model(cbc_glp_tran, name, false);
2786   if (returnCode != 0) {
2787     // errors
2788     glp_mpl_free_wksp(cbc_glp_tran);
2789     cbc_glp_tran = NULL;
2790     return 1;
2791   }
2792   if (dataName) {
2793     // read data
2794     strcpy(name, dataName);
2795     returnCode = glp_mpl_read_data(cbc_glp_tran, name);
2796     if (returnCode != 0) {
2797       // errors
2798       glp_mpl_free_wksp(cbc_glp_tran);
2799       cbc_glp_tran = NULL;
2800       return 1;
2801     }
2802   }
2803   // generate model
2804   returnCode = glp_mpl_generate(cbc_glp_tran, NULL);
2805   if (returnCode != 0) {
2806     // errors
2807     glp_mpl_free_wksp(cbc_glp_tran);
2808     cbc_glp_tran = NULL;
2809     return 2;
2810   }
2811   cbc_glp_prob = glp_create_prob();
2812   glp_mpl_build_prob(cbc_glp_tran, cbc_glp_prob);
2813   // Get number of rows, columns, and elements
2814   numberRows_ = glp_get_num_rows(cbc_glp_prob);
2815   numberColumns_ = glp_get_num_cols(cbc_glp_prob);
2816   numberElements_ = glp_get_num_nz(cbc_glp_prob);
2817   int iRow, iColumn;
2818   CoinBigIndex *start = new CoinBigIndex[numberRows_ + 1];
2819   int *index = new int[numberElements_];
2820   double *element = new double[numberElements_];
2821   // Row stuff
2822   rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
2823   rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
2824   // and objective
2825   objective_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2826   problemName_ = CoinStrdup(glp_get_prob_name(cbc_glp_prob));
2827   int kRow = 0;
2828   start[0] = 0;
2829   numberElements_ = 0;
2830   // spare space for checking
2831   double *el = new double[numberColumns_];
2832   int *ind = new int[numberColumns_];
2833   char **names = NULL;
2834   if (keepNames) {
2835     names = reinterpret_cast< char ** >(malloc(numberRows_ * sizeof(char *)));
2836     names_[0] = names;
2837     numberHash_[0] = numberRows_;
2838   }
2839   for (iRow = 0; iRow < numberRows_; iRow++) {
2840     int number = glp_get_mat_row(cbc_glp_prob, iRow + 1, ind - 1, el - 1);
2841     double rowLower, rowUpper;
2842     int rowType;
2843     rowLower = glp_get_row_lb(cbc_glp_prob, iRow + 1);
2844     rowUpper = glp_get_row_ub(cbc_glp_prob, iRow + 1);
2845     rowType = glp_get_row_type(cbc_glp_prob, iRow + 1);
2846     switch (rowType) {
2847     case GLP_LO:
2848       rowUpper = COIN_DBL_MAX;
2849       break;
2850     case GLP_UP:
2851       rowLower = -COIN_DBL_MAX;
2852       break;
2853     case GLP_FR:
2854       rowLower = -COIN_DBL_MAX;
2855       rowUpper = COIN_DBL_MAX;
2856       break;
2857     default:
2858       break;
2859     }
2860     rowlower_[kRow] = rowLower;
2861     rowupper_[kRow] = rowUpper;
2862     for (int i = 0; i < number; i++) {
2863       iColumn = ind[i] - 1;
2864       index[numberElements_] = iColumn;
2865       element[numberElements_++] = el[i];
2866     }
2867     if (keepNames) {
2868       strcpy(name, glp_get_row_name(cbc_glp_prob, iRow + 1));
2869       // could look at name?
2870       names[kRow] = CoinStrdup(name);
2871     }
2872     kRow++;
2873     start[kRow] = numberElements_;
2874   }
2875   delete[] el;
2876   delete[] ind;
2877 
2878   // FIXME why this variable is not used?
2879   bool minimize = (glp_get_obj_dir(cbc_glp_prob) == GLP_MAX ? false : true);
2880   // sign correct?
2881   objectiveOffset_ = glp_get_obj_coef(cbc_glp_prob, 0);
2882   for (int i = 0; i < numberColumns_; i++)
2883     objective_[i] = glp_get_obj_coef(cbc_glp_prob, i + 1);
2884   if (!minimize) {
2885     for (int i = 0; i < numberColumns_; i++)
2886       objective_[i] = -objective_[i];
2887     handler_->message(COIN_GENERAL_INFO, messages_) << " CoinMpsIO::readGMPL(): Maximization problem reformulated as minimization"
2888                                                     << CoinMessageEol;
2889     objectiveOffset_ = -objectiveOffset_;
2890   }
2891 
2892   // Matrix
2893   matrixByColumn_ = new CoinPackedMatrix(false, numberColumns_, numberRows_, numberElements_,
2894     element, index, start, NULL);
2895   matrixByColumn_->reverseOrdering();
2896   delete[] element;
2897   delete[] start;
2898   delete[] index;
2899   // Now do columns
2900   collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2901   colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2902   integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
2903   if (keepNames) {
2904     names = reinterpret_cast< char ** >(malloc(numberColumns_ * sizeof(char *)));
2905     names_[1] = names;
2906     numberHash_[1] = numberColumns_;
2907   }
2908   int numberIntegers = 0;
2909   for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2910     double columnLower = glp_get_col_lb(cbc_glp_prob, iColumn + 1);
2911     double columnUpper = glp_get_col_ub(cbc_glp_prob, iColumn + 1);
2912     int columnType = glp_get_col_type(cbc_glp_prob, iColumn + 1);
2913     switch (columnType) {
2914     case GLP_LO:
2915       columnUpper = COIN_DBL_MAX;
2916       break;
2917     case GLP_UP:
2918       columnLower = -COIN_DBL_MAX;
2919       break;
2920     case GLP_FR:
2921       columnLower = -COIN_DBL_MAX;
2922       columnUpper = COIN_DBL_MAX;
2923       break;
2924     default:
2925       break;
2926     }
2927     collower_[iColumn] = columnLower;
2928     colupper_[iColumn] = columnUpper;
2929     columnType = glp_get_col_kind(cbc_glp_prob, iColumn + 1);
2930     if (columnType == GLP_IV) {
2931       integerType_[iColumn] = 1;
2932       numberIntegers++;
2933       //assert ( collower_[iColumn] >= -MAX_INTEGER );
2934       if (collower_[iColumn] < -MAX_INTEGER)
2935         collower_[iColumn] = -MAX_INTEGER;
2936       if (colupper_[iColumn] > MAX_INTEGER)
2937         colupper_[iColumn] = MAX_INTEGER;
2938     } else if (columnType == GLP_BV) {
2939       numberIntegers++;
2940       integerType_[iColumn] = 1;
2941       collower_[iColumn] = 0.0;
2942       colupper_[iColumn] = 1.0;
2943     } else {
2944       integerType_[iColumn] = 0;
2945     }
2946     if (keepNames) {
2947       strcpy(name, glp_get_col_name(cbc_glp_prob, iColumn + 1));
2948       // could look at name?
2949       names[iColumn] = CoinStrdup(name);
2950     }
2951   }
2952   // leave in case report needed
2953   //glp_free(cbc_glp_prob);
2954   //glp_mpl_free_wksp(cbc_glp_tran);
2955   //glp_free_env();
2956   if (!numberIntegers) {
2957     free(integerType_);
2958     integerType_ = NULL;
2959   }
2960   if (handler_)
2961     handler_->message(COIN_MPS_STATS, messages_) << problemName_
2962                                                  << numberRows_
2963                                                  << numberColumns_
2964                                                  << numberElements_
2965                                                  << CoinMessageEol;
2966   return 0;
2967 #else
2968   printf("GLPK is not available\n");
2969   abort();
2970   return 1;
2971 #endif
2972 }
2973 //------------------------------------------------------------------
2974 // Read gams files
2975 //------------------------------------------------------------------
readGms(const char * filename,const char * extension,bool convertObjective)2976 int CoinMpsIO::readGms(const char *filename, const char *extension, bool convertObjective)
2977 {
2978   convertObjective_ = convertObjective;
2979   // Deal with filename - +1 if new, 0 if same as before, -1 if error
2980   CoinFileInput *input = 0;
2981   int returnCode = dealWithFileName(filename, extension, input);
2982   if (returnCode < 0) {
2983     return -1;
2984   } else if (returnCode > 0) {
2985     delete cardReader_;
2986     cardReader_ = new CoinMpsCardReader(input, this);
2987   }
2988   int numberSets = 0;
2989   CoinSet **sets = NULL;
2990   returnCode = readGms(numberSets, sets);
2991   for (int i = 0; i < numberSets; i++)
2992     delete sets[i];
2993   delete[] sets;
2994   return returnCode;
2995 }
readGms(const char * filename,const char * extension,int & numberSets,CoinSet ** & sets)2996 int CoinMpsIO::readGms(const char *filename, const char *extension,
2997   int &numberSets, CoinSet **&sets)
2998 {
2999   // Deal with filename - +1 if new, 0 if same as before, -1 if error
3000   CoinFileInput *input = 0;
3001   int returnCode = dealWithFileName(filename, extension, input);
3002   if (returnCode < 0) {
3003     return -1;
3004   } else if (returnCode > 0) {
3005     delete cardReader_;
3006     cardReader_ = new CoinMpsCardReader(input, this);
3007   }
3008   return readGms(numberSets, sets);
3009 }
readGms(int &,CoinSet ** &)3010 int CoinMpsIO::readGms(int & /*numberSets*/, CoinSet **& /*sets*/)
3011 {
3012   // First version expects comments giving size
3013   numberRows_ = 0;
3014   numberColumns_ = 0;
3015   numberElements_ = 0;
3016   bool gotName = false;
3017   bool minimize = false;
3018   char objName[COIN_MAX_FIELD_LENGTH];
3019   int decodeType = -1;
3020   while (!gotName) {
3021     if (cardReader_->nextGmsField(0) < 0) {
3022       handler_->message(COIN_MPS_EOF, messages_) << fileName_
3023                                                  << CoinMessageEol;
3024       return -3;
3025     } else {
3026       char *card = cardReader_->mutableCard();
3027       if (card[0] != '*') {
3028         // finished preamble without finding name
3029         printf("bad gms file\n");
3030         return -1;
3031       } else {
3032         // skip * and find next
3033         char *next = nextNonBlank(card + 1);
3034         if (!next)
3035           continue;
3036         if (decodeType >= 0) {
3037           // in middle of getting a total
3038           if (!strncmp(next, "Total", 5)) {
3039             // next line wanted
3040             decodeType += 100;
3041           } else if (decodeType >= 100) {
3042             decodeType -= 100;
3043             int number = atoi(next);
3044             assert(number > 0);
3045             if (decodeType == 0)
3046               numberRows_ = number;
3047             else if (decodeType == 1)
3048               numberColumns_ = number;
3049             else
3050               numberElements_ = number;
3051             decodeType = -1;
3052           }
3053         } else if (!strncmp(next, "Equation", 8)) {
3054           decodeType = 0;
3055         } else if (!strncmp(next, "Variable", 8)) {
3056           decodeType = 1;
3057         } else if (!strncmp(next, "Nonzero", 7)) {
3058           decodeType = 2;
3059         } else if (!strncmp(next, "Solve", 5)) {
3060           decodeType = -1;
3061           gotName = true;
3062           assert(numberRows_ > 0 && numberColumns_ > 0 && numberElements_ > 0);
3063           next = cardReader_->nextBlankOr(next + 5);
3064           char name[100];
3065           char *put = name;
3066           next = nextNonBlank(next);
3067           while (*next != ' ' && *next != '\t') {
3068             *put = *next;
3069             put++;
3070             next++;
3071           }
3072           *put = '\0';
3073           assert(put - name < 100);
3074           free(problemName_);
3075           problemName_ = CoinStrdup(name);
3076           next = strchr(next, ';');
3077           assert(next);
3078           // backup
3079           while (*next != ' ' && *next != '\t') {
3080             next--;
3081           }
3082           cardReader_->setPosition(next);
3083 #ifdef NDEBUG
3084           cardReader_->nextGmsField(1);
3085 #else
3086           int returnCode = cardReader_->nextGmsField(1);
3087           assert(!returnCode);
3088 #endif
3089           next = strchr(next, ';');
3090           cardReader_->setPosition(next + 1);
3091           strcpy(objName, cardReader_->columnName());
3092           char *semi = strchr(objName, ';');
3093           if (semi)
3094             *semi = '\0';
3095           if (strstr(card, "minim")) {
3096             minimize = true;
3097           } else {
3098             assert(strstr(card, "maxim"));
3099             minimize = false;
3100           }
3101         } else {
3102           decodeType = -1;
3103         }
3104       }
3105     }
3106   }
3107 
3108   objectiveOffset_ = 0.0;
3109   rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
3110   rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
3111   collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
3112   colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
3113   objective_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
3114   CoinBigIndex *start = reinterpret_cast< CoinBigIndex * >(malloc((numberRows_ + 1) * sizeof(CoinBigIndex)));
3115   COINColumnIndex *column = reinterpret_cast< COINRowIndex * >(malloc(numberElements_ * sizeof(COINRowIndex)));
3116   double *element = reinterpret_cast< double * >(malloc(numberElements_ * sizeof(double)));
3117   COINMpsType *rowType = reinterpret_cast< COINMpsType * >(malloc(numberRows_ * sizeof(COINMpsType)));
3118   char **rowName = reinterpret_cast< char ** >(malloc(numberRows_ * sizeof(char *)));
3119   COINMpsType *columnType = reinterpret_cast< COINMpsType * >(malloc(numberColumns_ * sizeof(COINMpsType)));
3120   char **columnName = reinterpret_cast< char ** >(malloc(numberColumns_ * sizeof(char *)));
3121 
3122   start[0] = 0;
3123   numberElements_ = 0;
3124 
3125   int numberErrors = 0;
3126   int i;
3127   COINColumnIndex numberIntegers = 0;
3128 
3129   // expect Variables
3130   int returnCode;
3131   returnCode = cardReader_->nextGmsField(1);
3132   assert(!returnCode && !strcmp(cardReader_->columnName(), "Variables"));
3133   for (i = 0; i < numberColumns_; i++) {
3134     returnCode = cardReader_->nextGmsField(1);
3135     assert(!returnCode);
3136     char *next = cardReader_->getPosition();
3137     if (*next == '\0') {
3138       // eol - expect , at beginning of next line
3139       returnCode = cardReader_->nextGmsField(0);
3140       assert(!returnCode);
3141       next = strchr(cardReader_->mutableCard(), ',');
3142       assert(next);
3143     }
3144     assert(*next == ',' || *next == ';');
3145     cardReader_->setPosition(next + 1);
3146     columnName[i] = CoinStrdup(cardReader_->columnName());
3147     // Default is free?
3148     collower_[i] = -COIN_DBL_MAX;
3149     // Surely not - check
3150     collower_[i] = 0.0;
3151     colupper_[i] = COIN_DBL_MAX;
3152     objective_[i] = 0.0;
3153     columnType[i] = COIN_UNSET_BOUND;
3154   }
3155   startHash(columnName, numberColumns_, 1);
3156   integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
3157   memset(integerType_, 0, numberColumns_);
3158   // Lists come in various flavors - I don't know many now
3159   // 0 - Positive
3160   // 1 - Binary
3161   // -1 end
3162   int listType = 10;
3163   while (listType >= 0) {
3164     returnCode = cardReader_->nextGmsField(1);
3165     assert(!returnCode);
3166     listType = -1;
3167     if (!strcmp(cardReader_->columnName(), "Positive")) {
3168       listType = 0;
3169     } else if (!strcmp(cardReader_->columnName(), "Binary")) {
3170       listType = 1;
3171     } else if (!strcmp(cardReader_->columnName(), "Integer")) {
3172       listType = 2;
3173     } else {
3174       break;
3175     }
3176     // skip Variables
3177     returnCode = cardReader_->nextGmsField(1);
3178     assert(!returnCode);
3179     assert(!strcmp(cardReader_->columnName(), "Variables"));
3180 
3181     // Go through lists
3182     bool inList = true;
3183     while (inList) {
3184       returnCode = cardReader_->nextGmsField(1);
3185       assert(!returnCode);
3186       char *next = cardReader_->getPosition();
3187       if (*next == '\0') {
3188         // eol - expect , at beginning of next line
3189         returnCode = cardReader_->nextGmsField(0);
3190         assert(!returnCode);
3191         next = strchr(cardReader_->mutableCard(), ',');
3192         assert(next);
3193       }
3194       assert(*next == ',' || *next == ';');
3195       cardReader_->setPosition(next + 1);
3196       inList = (*next == ',');
3197       int iColumn = findHash(cardReader_->columnName(), 1);
3198       assert(iColumn >= 0);
3199       if (listType == 0) {
3200         collower_[iColumn] = 0.0;
3201       } else if (listType == 1) {
3202         collower_[iColumn] = 0.0;
3203         colupper_[iColumn] = 1.0;
3204         columnType[iColumn] = COIN_BV_BOUND;
3205         integerType_[iColumn] = 1;
3206         numberIntegers++;
3207       } else if (listType == 2) {
3208         collower_[iColumn] = 0.0;
3209         columnType[iColumn] = COIN_UI_BOUND;
3210         integerType_[iColumn] = 1;
3211         numberIntegers++;
3212       }
3213     }
3214   }
3215   // should be equations
3216   assert(!strcmp(cardReader_->columnName(), "Equations"));
3217   for (i = 0; i < numberRows_; i++) {
3218     returnCode = cardReader_->nextGmsField(1);
3219     assert(!returnCode);
3220     char *next = cardReader_->getPosition();
3221     if (*next == '\0') {
3222       // eol - expect , at beginning of next line
3223       returnCode = cardReader_->nextGmsField(0);
3224       assert(!returnCode);
3225       next = strchr(cardReader_->mutableCard(), ',');
3226       assert(next);
3227     }
3228     assert(*next == ',' || *next == ';');
3229     cardReader_->setPosition(next + 1);
3230     rowName[i] = CoinStrdup(cardReader_->columnName());
3231     // Default is free?
3232     rowlower_[i] = -COIN_DBL_MAX;
3233     rowupper_[i] = COIN_DBL_MAX;
3234     rowType[i] = COIN_N_ROW;
3235   }
3236   startHash(rowName, numberRows_, 0);
3237   const double largeElement = 1.0e14;
3238   int numberTiny = 0;
3239   int numberLarge = 0;
3240   // For now expect just equations so do loop
3241   for (i = 0; i < numberRows_; i++) {
3242     returnCode = cardReader_->nextGmsField(1);
3243     assert(!returnCode);
3244     char *next = cardReader_->getPosition();
3245     assert(*next == ' ');
3246     char rowName[COIN_MAX_FIELD_LENGTH];
3247     strcpy(rowName, cardReader_->columnName());
3248     char *dot = strchr(rowName, '.');
3249     assert(dot);
3250     *dot = '\0';
3251     assert(*(dot + 1) == '.');
3252 #ifndef NDEBUG
3253     int iRow = findHash(rowName, 0);
3254     assert(i == iRow);
3255 #endif
3256     returnCode = 0;
3257     while (!returnCode) {
3258       returnCode = cardReader_->nextGmsField(3);
3259       assert(returnCode == 0 || returnCode == 2);
3260       if (returnCode == 2)
3261         break;
3262       int iColumn = findHash(cardReader_->columnName(), 1);
3263       if (iColumn >= 0) {
3264         column[numberElements_] = iColumn;
3265         double value = cardReader_->value();
3266         if (fabs(value) < smallElement_)
3267           numberTiny++;
3268         else if (fabs(value) > largeElement)
3269           numberLarge++;
3270         element[numberElements_++] = value;
3271       } else {
3272         // may be string
3273         char temp[100];
3274         strcpy(temp, cardReader_->columnName());
3275         char *ast = strchr(temp, '*');
3276         if (!ast) {
3277           assert(iColumn >= 0);
3278         } else {
3279           assert(allowStringElements_);
3280           *ast = '\0';
3281           if (allowStringElements_ == 1)
3282             iColumn = findHash(temp, 1);
3283           else
3284             iColumn = findHash(ast + 1, 1);
3285           assert(iColumn >= 0);
3286           char temp2[100];
3287           temp2[0] = '\0';
3288           double value = cardReader_->value();
3289           if (value && value != 1.0)
3290             sprintf(temp2, "%g*", value);
3291           if (allowStringElements_ == 1)
3292             strcat(temp2, ast + 1);
3293           else
3294             strcat(temp2, temp);
3295           addString(i, iColumn, temp2);
3296         }
3297       }
3298     }
3299     start[i + 1] = numberElements_;
3300     next = cardReader_->getPosition();
3301     // what about ranges?
3302     COINMpsType type = COIN_N_ROW;
3303     if (!strncmp(next, "=E=", 3))
3304       type = COIN_E_ROW;
3305     else if (!strncmp(next, "=G=", 3))
3306       type = COIN_G_ROW;
3307     else if (!strncmp(next, "=L=", 3))
3308       type = COIN_L_ROW;
3309     assert(type != COIN_N_ROW);
3310     cardReader_->setPosition(next + 3);
3311     returnCode = cardReader_->nextGmsField(2);
3312     assert(!returnCode);
3313     if (type == COIN_E_ROW) {
3314       rowlower_[i] = cardReader_->value();
3315       rowupper_[i] = cardReader_->value();
3316     } else if (type == COIN_G_ROW) {
3317       rowlower_[i] = cardReader_->value();
3318     } else if (type == COIN_L_ROW) {
3319       rowupper_[i] = cardReader_->value();
3320     }
3321     rowType[i] = type;
3322     // and skip ;
3323 #ifdef NDEBUG
3324     cardReader_->nextGmsField(5);
3325 #else
3326     returnCode = cardReader_->nextGmsField(5);
3327     assert(!returnCode);
3328 #endif
3329   }
3330   // Now non default bounds
3331   while (true) {
3332     returnCode = cardReader_->nextGmsField(0);
3333     if (returnCode < 0)
3334       break;
3335     // if there is a . see if valid name
3336     char *card = cardReader_->mutableCard();
3337     char *dot = strchr(card, '.');
3338     if (dot) {
3339       *dot = '\0';
3340       int iColumn = findHash(card, 1);
3341       if (iColumn >= 0) {
3342         // bound
3343         char *next = strchr(dot + 1, '=');
3344         assert(next);
3345         double value = atof(next + 1);
3346         if (!strncmp(dot + 1, "fx", 2)) {
3347           collower_[iColumn] = value;
3348           colupper_[iColumn] = value;
3349         } else if (!strncmp(dot + 1, "up", 2)) {
3350           colupper_[iColumn] = value;
3351         } else if (!strncmp(dot + 1, "lo", 2)) {
3352           collower_[iColumn] = value;
3353         }
3354       }
3355       // may be two per card
3356       char *semi = strchr(dot + 1, ';');
3357       dot = NULL;
3358       if (semi)
3359         dot = strchr(semi + 1, '.');
3360       if (dot) {
3361         char *next = nextNonBlank(semi + 1);
3362         dot = strchr(next, '.');
3363         assert(dot);
3364         *dot = '\0';
3365         assert(iColumn == findHash(next, 1));
3366         // bound
3367         next = strchr(dot + 1, '=');
3368         assert(next);
3369         double value = atof(next + 1);
3370         if (!strncmp(dot + 1, "fx", 2)) {
3371           collower_[iColumn] = value;
3372           abort();
3373           colupper_[iColumn] = value;
3374         } else if (!strncmp(dot + 1, "up", 2)) {
3375           colupper_[iColumn] = value;
3376         } else if (!strncmp(dot + 1, "lo", 2)) {
3377           collower_[iColumn] = value;
3378         }
3379         // may be two per card
3380         semi = strchr(dot + 1, ';');
3381         assert(semi);
3382       }
3383     }
3384   }
3385   // Objective
3386   int iObjCol = findHash(objName, 1);
3387   int iObjRow = -1;
3388   assert(iObjCol >= 0);
3389   if (!convertObjective_) {
3390     objective_[iObjCol] = minimize ? 1.0 : -1.0;
3391   } else {
3392     // move column stuff
3393     COINColumnIndex iColumn;
3394     free(names_[1][iObjCol]);
3395     for (iColumn = iObjCol + 1; iColumn < numberColumns_; iColumn++) {
3396       integerType_[iColumn - 1] = integerType_[iColumn];
3397       collower_[iColumn - 1] = collower_[iColumn];
3398       colupper_[iColumn - 1] = colupper_[iColumn];
3399       names_[1][iColumn - 1] = names_[1][iColumn];
3400     }
3401     numberHash_[1]--;
3402     numberColumns_--;
3403     double multiplier = minimize ? 1.0 : -1.0;
3404     // but swap
3405     multiplier *= -1.0;
3406     int iRow;
3407     CoinBigIndex nel = 0;
3408     CoinBigIndex last = 0;
3409     int kRow = 0;
3410     for (iRow = 0; iRow < numberRows_; iRow++) {
3411       CoinBigIndex j;
3412       bool found = false;
3413       for (j = last; j < start[iRow + 1]; j++) {
3414         int iColumn = column[j];
3415         if (iColumn != iObjCol) {
3416           column[nel] = (iColumn < iObjCol) ? iColumn : iColumn - 1;
3417           element[nel++] = element[j];
3418         } else {
3419           found = true;
3420           assert(element[j] == 1.0);
3421           break;
3422         }
3423       }
3424       if (!found) {
3425         last = start[iRow + 1];
3426         rowlower_[kRow] = rowlower_[iRow];
3427         rowupper_[kRow] = rowupper_[iRow];
3428         names_[0][kRow] = names_[0][iRow];
3429         start[kRow + 1] = nel;
3430         kRow++;
3431       } else {
3432         free(names_[0][iRow]);
3433         iObjRow = iRow;
3434         for (j = last; j < start[iRow + 1]; j++) {
3435           int iColumn = column[j];
3436           if (iColumn != iObjCol) {
3437             if (iColumn > iObjCol)
3438               iColumn--;
3439             objective_[iColumn] = multiplier * element[j];
3440           }
3441         }
3442         nel = start[kRow];
3443         last = start[iRow + 1];
3444       }
3445     }
3446     numberRows_ = kRow;
3447     assert(iObjRow >= 0);
3448     numberHash_[0]--;
3449   }
3450   stopHash(0);
3451   stopHash(1);
3452   // clean up integers
3453   if (!numberIntegers) {
3454     free(integerType_);
3455     integerType_ = NULL;
3456   } else {
3457     COINColumnIndex iColumn;
3458     for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3459       if (integerType_[iColumn]) {
3460         //assert ( collower_[iColumn] >= -MAX_INTEGER );
3461         if (collower_[iColumn] < -MAX_INTEGER)
3462           collower_[iColumn] = -MAX_INTEGER;
3463         if (colupper_[iColumn] > MAX_INTEGER)
3464           colupper_[iColumn] = MAX_INTEGER;
3465       }
3466     }
3467   }
3468   free(columnType);
3469   free(rowType);
3470   if (numberStringElements() && convertObjective_) {
3471     int numberElements = numberStringElements();
3472     for (int i = 0; i < numberElements; i++) {
3473       char *line = stringElements_[i];
3474       int iRow;
3475       int iColumn;
3476       sscanf(line, "%d,%d,", &iRow, &iColumn);
3477       bool modify = false;
3478       if (iRow > iObjRow) {
3479         modify = true;
3480         iRow--;
3481       }
3482       if (iColumn > iObjCol) {
3483         modify = true;
3484         iColumn--;
3485       }
3486       if (modify) {
3487         char temp[500];
3488         const char *pos = strchr(line, ',');
3489         assert(pos);
3490         pos = strchr(pos + 1, ',');
3491         assert(pos);
3492         pos++;
3493         sprintf(temp, "%d,%d,%s", iRow, iColumn, pos);
3494         free(line);
3495         stringElements_[i] = CoinStrdup(temp);
3496       }
3497     }
3498   }
3499   // construct packed matrix and convert to column format
3500   CoinPackedMatrix matrixByRow(false,
3501     numberColumns_, numberRows_, numberElements_,
3502     element, column, start, NULL);
3503   free(column);
3504   free(start);
3505   free(element);
3506   matrixByColumn_ = new CoinPackedMatrix();
3507   matrixByColumn_->setExtraGap(0.0);
3508   matrixByColumn_->setExtraMajor(0.0);
3509   matrixByColumn_->reverseOrderedCopyOf(matrixByRow);
3510   if (!convertObjective_)
3511     assert(matrixByColumn_->getVectorLengths()[iObjCol] == 1);
3512 
3513   handler_->message(COIN_MPS_STATS, messages_) << problemName_
3514                                                << numberRows_
3515                                                << numberColumns_
3516                                                << numberElements_
3517                                                << CoinMessageEol;
3518   if ((numberTiny || numberLarge) && handler_->logLevel() > 3)
3519     printf("There were %d coefficients < %g and %d > %g\n",
3520       numberTiny, smallElement_, numberLarge, largeElement);
3521   return numberErrors;
3522 }
3523 /* Read a basis in MPS format from the given filename.
3524    If VALUES on NAME card and solution not NULL fills in solution
3525    status values as for CoinWarmStartBasis (but one per char)
3526 
3527    Use "stdin" or "-" to read from stdin.
3528 */
readBasis(const char * filename,const char * extension,double * solution,unsigned char * rowStatus,unsigned char * columnStatus,const std::vector<std::string> & colnames,int numberColumns,const std::vector<std::string> & rownames,int numberRows)3529 int CoinMpsIO::readBasis(const char *filename, const char *extension,
3530   double *solution, unsigned char *rowStatus, unsigned char *columnStatus,
3531   const std::vector< std::string > &colnames, int numberColumns,
3532   const std::vector< std::string > &rownames, int numberRows)
3533 {
3534   // Deal with filename - +1 if new, 0 if same as before, -1 if error
3535   CoinFileInput *input = 0;
3536   int returnCode = dealWithFileName(filename, extension, input);
3537   if (returnCode < 0) {
3538     return -1;
3539   } else if (returnCode > 0) {
3540     delete cardReader_;
3541     cardReader_ = new CoinMpsCardReader(input, this);
3542   }
3543 
3544   cardReader_->readToNextSection();
3545 
3546   if (cardReader_->whichSection() == COIN_NAME_SECTION) {
3547     // Get whether to use values (passed back by freeFormat)
3548     if (!cardReader_->freeFormat())
3549       solution = NULL;
3550 
3551   } else if (cardReader_->whichSection() == COIN_UNKNOWN_SECTION) {
3552     handler_->message(COIN_MPS_BADFILE1, messages_) << cardReader_->card()
3553                                                     << 1
3554                                                     << fileName_
3555                                                     << CoinMessageEol;
3556     if (cardReader_->fileInput()->getReadType() != "plain")
3557       handler_->message(COIN_MPS_BADFILE2, messages_)
3558         << cardReader_->fileInput()->getReadType()
3559         << CoinMessageEol;
3560 
3561     return -2;
3562   } else if (cardReader_->whichSection() != COIN_EOF_SECTION) {
3563     return -4;
3564   } else {
3565     handler_->message(COIN_MPS_EOF, messages_) << fileName_
3566                                                << CoinMessageEol;
3567     return -3;
3568   }
3569   numberRows_ = numberRows;
3570   numberColumns_ = numberColumns;
3571   // bas file - always read in free format
3572   bool gotNames;
3573   if (rownames.size() != static_cast< unsigned int >(numberRows_) || colnames.size() != static_cast< unsigned int >(numberColumns_)) {
3574     gotNames = false;
3575   } else {
3576     gotNames = true;
3577     numberHash_[0] = numberRows_;
3578     numberHash_[1] = numberColumns_;
3579     names_[0] = reinterpret_cast< char ** >(malloc(numberRows_ * sizeof(char *)));
3580     names_[1] = reinterpret_cast< char ** >(malloc(numberColumns_ * sizeof(char *)));
3581     const char **rowNames = const_cast< const char ** >(names_[0]);
3582     const char **columnNames = const_cast< const char ** >(names_[1]);
3583     int i;
3584     for (i = 0; i < numberRows_; ++i) {
3585       rowNames[i] = rownames[i].c_str();
3586     }
3587     for (i = 0; i < numberColumns_; ++i) {
3588       columnNames[i] = colnames[i].c_str();
3589     }
3590     startHash(const_cast< char ** >(rowNames), numberRows, 0);
3591     startHash(const_cast< char ** >(columnNames), numberColumns, 1);
3592   }
3593   cardReader_->setWhichSection(COIN_BASIS_SECTION);
3594   cardReader_->setFreeFormat(true);
3595   // below matches CoinWarmStartBasis,
3596   const unsigned char basic = 0x01;
3597   const unsigned char atLowerBound = 0x03;
3598   const unsigned char atUpperBound = 0x02;
3599   while (cardReader_->nextField() == COIN_BASIS_SECTION) {
3600     // Get type and column number
3601     int iColumn;
3602     if (gotNames) {
3603       iColumn = findHash(cardReader_->columnName(), 1);
3604     } else {
3605       // few checks
3606       char check;
3607       sscanf(cardReader_->columnName(), "%c%d", &check, &iColumn);
3608       assert(check == 'C' && iColumn >= 0);
3609       if (iColumn >= numberColumns_)
3610         iColumn = -1;
3611     }
3612     if (iColumn >= 0) {
3613       double value = cardReader_->value();
3614       if (solution && value > -1.0e50)
3615         solution[iColumn] = value;
3616       int iRow = -1;
3617       switch (cardReader_->mpsType()) {
3618       case COIN_BS_BASIS:
3619         columnStatus[iColumn] = basic;
3620         break;
3621       case COIN_XL_BASIS:
3622         columnStatus[iColumn] = basic;
3623         // get row number
3624         if (gotNames) {
3625           iRow = findHash(cardReader_->rowName(), 0);
3626         } else {
3627           // few checks
3628           char check;
3629           sscanf(cardReader_->rowName(), "%c%d", &check, &iRow);
3630           assert(check == 'R' && iRow >= 0);
3631           if (iRow >= numberRows_)
3632             iRow = -1;
3633         }
3634         if (iRow >= 0) {
3635           rowStatus[iRow] = atLowerBound;
3636         }
3637         break;
3638       case COIN_XU_BASIS:
3639         columnStatus[iColumn] = basic;
3640         // get row number
3641         if (gotNames) {
3642           iRow = findHash(cardReader_->rowName(), 0);
3643         } else {
3644           // few checks
3645           char check;
3646           sscanf(cardReader_->rowName(), "%c%d", &check, &iRow);
3647           assert(check == 'R' && iRow >= 0);
3648           if (iRow >= numberRows_)
3649             iRow = -1;
3650         }
3651         if (iRow >= 0) {
3652           rowStatus[iRow] = atUpperBound;
3653         }
3654         break;
3655       case COIN_LL_BASIS:
3656         columnStatus[iColumn] = atLowerBound;
3657         break;
3658       case COIN_UL_BASIS:
3659         columnStatus[iColumn] = atUpperBound;
3660         break;
3661       default:
3662         break;
3663       }
3664     }
3665   }
3666   if (gotNames) {
3667     stopHash(0);
3668     stopHash(1);
3669     free(names_[0]);
3670     names_[0] = NULL;
3671     numberHash_[0] = 0;
3672     free(names_[1]);
3673     names_[1] = NULL;
3674     numberHash_[1] = 0;
3675     delete[] hash_[0];
3676     delete[] hash_[1];
3677     hash_[0] = 0;
3678     hash_[1] = 0;
3679   }
3680   if (cardReader_->whichSection() != COIN_ENDATA_SECTION) {
3681     handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
3682                                                     << cardReader_->card()
3683                                                     << CoinMessageEol;
3684     handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
3685     return -1;
3686   } else {
3687     return solution ? 1 : 0;
3688   }
3689 }
3690 
3691 //------------------------------------------------------------------
3692 
3693 // Function to create row name field
3694 static void
convertRowName(int formatType,const char * name,char outputRow[100])3695 convertRowName(int formatType, const char *name, char outputRow[100])
3696 {
3697   strcpy(outputRow, name);
3698   if (!formatType) {
3699     int i;
3700     // pad out to 8
3701     for (i = 0; i < 8; i++) {
3702       if (outputRow[i] == '\0')
3703         break;
3704     }
3705     for (; i < 8; i++)
3706       outputRow[i] = ' ';
3707     outputRow[8] = '\0';
3708   } else if (formatType > 1 && formatType < 8) {
3709     int i;
3710     // pad out to 8
3711     for (i = 0; i < 8; i++) {
3712       if (outputRow[i] == '\0')
3713         break;
3714     }
3715     for (; i < 8; i++)
3716       outputRow[i] = ' ';
3717     outputRow[8] = '\0';
3718   }
3719 }
3720 // Function to return number in most efficient way
3721 // Also creates row name field
3722 /* formatType is
3723    0 - normal and 8 character names
3724    1 - extra accuracy
3725    2 - IEEE hex - INTEL
3726    3 - IEEE hex - not INTEL
3727 */
3728 static void
convertDouble(int section,int formatType,double value,char outputValue[24],const char * name,char outputRow[100])3729 convertDouble(int section, int formatType, double value, char outputValue[24],
3730   const char *name, char outputRow[100])
3731 {
3732   convertRowName(formatType, name, outputRow);
3733   CoinConvertDouble(section, formatType & 3, value, outputValue);
3734 }
3735 // Function to return number in most efficient way
3736 /* formatType is
3737    0 - normal and 8 character names
3738    1 - extra accuracy
3739    2 - IEEE hex - INTEL
3740    3 - IEEE hex - not INTEL
3741 */
CoinConvertDouble(int section,int formatType,double value,char outputValue[24])3742 void CoinConvertDouble(int section, int formatType, double value, char outputValue[24])
3743 {
3744   if (formatType == 0) {
3745     bool stripZeros = true;
3746     if (fabs(value) < 1.0e40) {
3747       int power10, decimal;
3748       if (value >= 0.0) {
3749         power10 = static_cast< int >(log10(value));
3750         if (power10 < 9 && power10 > -4) {
3751           decimal = CoinMin(10, 10 - power10);
3752           char format[8];
3753           sprintf(format, "%%12.%df", decimal);
3754           sprintf(outputValue, format, value);
3755         } else {
3756           sprintf(outputValue, "%13.7g", value);
3757           stripZeros = false;
3758         }
3759       } else {
3760         power10 = static_cast< int >(log10(-value)) + 1;
3761         if (power10 < 8 && power10 > -3) {
3762           decimal = CoinMin(9, 9 - power10);
3763           char format[8];
3764           sprintf(format, "%%12.%df", decimal);
3765           sprintf(outputValue, format, value);
3766         } else {
3767           sprintf(outputValue, "%13.6g", value);
3768           stripZeros = false;
3769         }
3770       }
3771       if (stripZeros) {
3772         // take off trailing 0
3773         int j;
3774         for (j = 11; j >= 0; j--) {
3775           if (outputValue[j] == '0')
3776             outputValue[j] = ' ';
3777           else
3778             break;
3779         }
3780       } else {
3781         // still need to make sure fits in 12 characters
3782         char *e = strchr(outputValue, 'e');
3783         if (!e) {
3784           // no e but better make sure fits in 12
3785           if (outputValue[12] != ' ' && outputValue[12] != '\0') {
3786             assert(outputValue[0] == ' ');
3787             int j;
3788             for (j = 0; j < 12; j++)
3789               outputValue[j] = outputValue[j + 1];
3790           }
3791           outputValue[12] = '\0';
3792         } else {
3793           // e take out 0s
3794           int j = static_cast< int >((e - outputValue)) + 1;
3795           int put = j + 1;
3796           assert(outputValue[j] == '-' || outputValue[j] == '+');
3797           for (j = put; j < 14; j++) {
3798             if (outputValue[j] != '0')
3799               break;
3800           }
3801           if (j == put) {
3802             // we need to lose something
3803             // try taking out blanks
3804             if (outputValue[0] == ' ') {
3805               // skip blank
3806               j = 1;
3807               put = 0;
3808             } else {
3809               // rounding will be wrong but ....
3810               put -= 3; // points to one before e
3811               j -= 2; // points to e
3812             }
3813           }
3814           // copy rest
3815           for (; j < 14; j++) {
3816             outputValue[put++] = outputValue[j];
3817           }
3818         }
3819       }
3820       // overwrite if very very small
3821       if (fabs(value) < 1.0e-20)
3822         strcpy(outputValue, "0.0");
3823     } else {
3824       if (section == 2) {
3825         outputValue[0] = '\0'; // needs no value
3826       } else {
3827         // probably error ... but ....
3828         sprintf(outputValue, "%12.6g", value);
3829       }
3830     }
3831     int i;
3832     // pad out to 12
3833     for (i = 0; i < 12; i++) {
3834       if (outputValue[i] == '\0')
3835         break;
3836     }
3837     for (; i < 12; i++)
3838       outputValue[i] = ' ';
3839     outputValue[12] = '\0';
3840   } else if (formatType == 1) {
3841     if (fabs(value) < 1.0e40) {
3842       memset(outputValue, ' ', 24);
3843       sprintf(outputValue, "%.16g", value);
3844       // take out blanks
3845       int i = 0;
3846       int j;
3847       for (j = 0; j < 23; j++) {
3848         if (outputValue[j] != ' ')
3849           outputValue[i++] = outputValue[j];
3850       }
3851       outputValue[i] = '\0';
3852     } else {
3853       if (section == 2) {
3854         outputValue[0] = '\0'; // needs no value
3855       } else {
3856         // probably error ... but ....
3857         sprintf(outputValue, "%12.6g", value);
3858       }
3859     }
3860   } else {
3861     // IEEE
3862     // ieee - 3 bytes go to 2
3863     assert(sizeof(double) == 8 * sizeof(char));
3864     assert(sizeof(unsigned short) == 2 * sizeof(char));
3865     unsigned short shortValue[4];
3866     memcpy(shortValue, &value, sizeof(double));
3867     outputValue[12] = '\0';
3868     if (formatType == 2) {
3869       // INTEL
3870       char *thisChar = outputValue;
3871       for (int i = 3; i >= 0; i--) {
3872         unsigned short thisValue = shortValue[i];
3873         // encode 6 bits at a time
3874         for (int j = 0; j < 3; j++) {
3875           unsigned short thisPart = static_cast< unsigned short >(thisValue & 63);
3876           thisValue = static_cast< unsigned short >(thisValue >> 6);
3877           if (thisPart < 10) {
3878             *thisChar = static_cast< char >(thisPart + '0');
3879           } else if (thisPart < 36) {
3880             *thisChar = static_cast< char >(thisPart - 10 + 'a');
3881           } else if (thisPart < 62) {
3882             *thisChar = static_cast< char >(thisPart - 36 + 'A');
3883           } else {
3884             *thisChar = static_cast< char >(thisPart - 62 + '*');
3885           }
3886           thisChar++;
3887         }
3888       }
3889     } else {
3890       // not INTEL
3891       char *thisChar = outputValue;
3892       for (int i = 0; i < 4; i++) {
3893         unsigned short thisValue = shortValue[i];
3894         // encode 6 bits at a time
3895         for (int j = 0; j < 3; j++) {
3896           unsigned short thisPart = static_cast< unsigned short >(thisValue & 63);
3897           thisValue = static_cast< unsigned short >(thisValue >> 6);
3898           if (thisPart < 10) {
3899             *thisChar = static_cast< char >(thisPart + '0');
3900           } else if (thisPart < 36) {
3901             *thisChar = static_cast< char >(thisPart - 10 + 'a');
3902           } else if (thisPart < 62) {
3903             *thisChar = static_cast< char >(thisPart - 36 + 'A');
3904           } else {
3905             *thisChar = static_cast< char >(thisPart - 62 + '*');
3906           }
3907           thisChar++;
3908         }
3909       }
3910     }
3911   }
3912 }
3913 static void
writeString(CoinFileOutput * output,const char * str)3914 writeString(CoinFileOutput *output, const char *str)
3915 {
3916   if (output != 0) {
3917     output->puts(str);
3918   }
3919 }
3920 
3921 // Put out card image
outputCard(int formatType,int numberFields,CoinFileOutput * output,std::string head,const char * name,const char outputValue[2][24],const char outputRow[2][100])3922 static void outputCard(int formatType, int numberFields,
3923   CoinFileOutput *output,
3924   std::string head, const char *name,
3925   const char outputValue[2][24],
3926   const char outputRow[2][100])
3927 {
3928   // fprintf(fp,"%s",head.c_str());
3929   std::string line = head;
3930   int i;
3931   if (formatType == 0 || (formatType >= 2 && formatType < 8)) {
3932     char outputColumn[9];
3933     strcpy(outputColumn, name);
3934     for (i = 0; i < 8; i++) {
3935       if (outputColumn[i] == '\0')
3936         break;
3937     }
3938     for (; i < 8; i++)
3939       outputColumn[i] = ' ';
3940     outputColumn[8] = '\0';
3941     // fprintf(fp,"%s  ",outputColumn);
3942     line += outputColumn;
3943     line += "  ";
3944     for (i = 0; i < numberFields; i++) {
3945       // fprintf(fp,"%s  %s",outputRow[i],outputValue[i]);
3946       line += outputRow[i];
3947       line += "  ";
3948       line += outputValue[i];
3949       if (i < numberFields - 1) {
3950         // fprintf(fp,"   ");
3951         line += "   ";
3952       }
3953     }
3954   } else {
3955     // fprintf(fp,"%s",name);
3956     line += name;
3957     for (i = 0; i < numberFields; i++) {
3958       // fprintf(fp," %s %s",outputRow[i],outputValue[i]);
3959       line += " ";
3960       line += outputRow[i];
3961       line += " ";
3962       line += outputValue[i];
3963     }
3964   }
3965 
3966   // fprintf(fp,"\n");
3967   line += "\n";
3968   writeString(output, line.c_str());
3969 }
3970 static int
makeUniqueNames(char ** names,int number,char first)3971 makeUniqueNames(char **names, int number, char first)
3972 {
3973   int largest = -1;
3974   int i;
3975   for (i = 0; i < number; i++) {
3976     char *name = names[i];
3977     if (name[0] == first && strlen(name) == 8) {
3978       // check number
3979       int n = 0;
3980       for (int j = 1; j < 8; j++) {
3981         char num = name[j];
3982         if (num >= '0' && num <= '9') {
3983           n *= 10;
3984           n += num - '0';
3985         } else {
3986           n = -1;
3987           break;
3988         }
3989       }
3990       if (n >= 0)
3991         largest = CoinMax(largest, n);
3992     }
3993   }
3994   largest++;
3995   if (largest > 0) {
3996     // check
3997     char *used = new char[largest];
3998     memset(used, 0, largest);
3999     int nDup = 0;
4000     for (i = 0; i < number; i++) {
4001       char *name = names[i];
4002       if (name[0] == first && strlen(name) == 8) {
4003         // check number
4004         int n = 0;
4005         for (int j = 1; j < 8; j++) {
4006           char num = name[j];
4007           if (num >= '0' && num <= '9') {
4008             n *= 10;
4009             n += num - '0';
4010           } else {
4011             n = -1;
4012             break;
4013           }
4014         }
4015         if (n >= 0) {
4016           if (!used[n]) {
4017             used[n] = 1;
4018           } else {
4019             // duplicate
4020             nDup++;
4021             free(names[i]);
4022             char newName[12];
4023             sprintf(newName, "%c%7.7d", first, largest);
4024             names[i] = CoinStrdup(newName);
4025             largest++;
4026           }
4027         }
4028       }
4029     }
4030     delete[] used;
4031     return nDup;
4032   } else {
4033     return 0;
4034   }
4035 }
4036 static void
strcpyeq(char * output,const char * input)4037 strcpyeq(char *output, const char *input)
4038 {
4039   output[0] = '=';
4040   strcpy(output + 1, input);
4041 }
4042 
writeMps(const char * filename,int compression,int formatType,int numberAcross,CoinPackedMatrix * quadratic,int numberSOS,const CoinSet * setInfo) const4043 int CoinMpsIO::writeMps(const char *filename, int compression,
4044   int formatType, int numberAcross,
4045   CoinPackedMatrix *quadratic,
4046   int numberSOS, const CoinSet *setInfo) const
4047 {
4048   // Clean up format and numberacross
4049   numberAcross = CoinMax(1, numberAcross);
4050   numberAcross = CoinMin(2, numberAcross);
4051   formatType = CoinMax(0, formatType);
4052   formatType = CoinMin(2, formatType);
4053   int possibleCompression = 0;
4054 #ifdef COIN_HAS_ZLIB
4055   possibleCompression = 1;
4056 #endif
4057 #ifdef COIN_HAS_BZLIB
4058   possibleCompression += 2;
4059 #endif
4060   if ((compression & possibleCompression) == 0) {
4061     // switch to other if possible
4062     if (compression && possibleCompression)
4063       compression = 3 - compression;
4064     else
4065       compression = 0;
4066   }
4067   std::string line = filename;
4068   CoinFileOutput *output = 0;
4069   switch (compression) {
4070   case 1:
4071     if (strcmp(line.c_str() + (line.size() - 3), ".gz") != 0) {
4072       line += ".gz";
4073     }
4074     output = CoinFileOutput::create(line, CoinFileOutput::COMPRESS_GZIP);
4075     break;
4076 
4077   case 2:
4078     if (strcmp(line.c_str() + (line.size() - 4), ".bz2") != 0) {
4079       line += ".bz2";
4080     }
4081     output = CoinFileOutput::create(line, CoinFileOutput::COMPRESS_BZIP2);
4082     break;
4083 
4084   case 0:
4085   default:
4086     output = CoinFileOutput::create(line, CoinFileOutput::COMPRESS_NONE);
4087     break;
4088   }
4089 
4090   // Set locale so won't get , instead of .
4091   char *saveLocale = strdup(setlocale(LC_ALL, NULL));
4092   setlocale(LC_ALL, "C");
4093   const char *const *const rowNames = names_[0];
4094   const char *const *const columnNames = names_[1];
4095   int i;
4096   unsigned int length = 8;
4097   bool freeFormat = (formatType == 1);
4098   // Check names for uniqueness if default
4099   int nChanged;
4100   nChanged = makeUniqueNames(names_[0], numberRows_, 'R');
4101   if (nChanged)
4102     handler_->message(COIN_MPS_CHANGED, messages_) << "row" << nChanged
4103                                                    << CoinMessageEol;
4104   nChanged = makeUniqueNames(names_[1], numberColumns_, 'C');
4105   if (nChanged)
4106     handler_->message(COIN_MPS_CHANGED, messages_) << "column" << nChanged
4107                                                    << CoinMessageEol;
4108   for (i = 0; i < numberRows_; ++i) {
4109     if (strlen(rowNames[i]) > length) {
4110       length = static_cast< int >(strlen(rowNames[i]));
4111       break;
4112     }
4113   }
4114   if (length <= 8) {
4115     for (i = 0; i < numberColumns_; ++i) {
4116       if (strlen(columnNames[i]) > length) {
4117         length = static_cast< int >(strlen(columnNames[i]));
4118         break;
4119       }
4120     }
4121   }
4122   if (length > 8 && freeFormat != 1) {
4123     freeFormat = true;
4124     formatType += 8;
4125   }
4126   if (numberStringElements_) {
4127     freeFormat = true;
4128     numberAcross = 1;
4129   }
4130 
4131   // NAME card
4132 
4133   line = "NAME          ";
4134   if (strcmp(problemName_, "") == 0) {
4135     line.append("BLANK   ");
4136   } else {
4137     if (strlen(problemName_) >= 8) {
4138       line.append(problemName_, 8);
4139     } else {
4140       line.append(problemName_);
4141       line.append(8 - strlen(problemName_), ' ');
4142     }
4143   }
4144   if (freeFormat && (formatType & 7) != 2)
4145     line.append("  FREE");
4146   else if (freeFormat)
4147     line.append("  FREEIEEE");
4148   else if ((formatType & 7) == 2)
4149     line.append("  IEEE");
4150   // See if INTEL if IEEE
4151   if ((formatType & 7) == 2) {
4152     // test intel here and add 1 if not intel
4153     double value = 1.0;
4154     char x[8];
4155     memcpy(x, &value, 8);
4156     if (x[0] == 63) {
4157       formatType++; // not intel
4158     } else {
4159       assert(x[0] == 0);
4160     }
4161   }
4162   // finish off name and do ROWS card and objective
4163   char *objrow = CoinStrdup(strcmp(objectiveName_, "") == 0 ? "OBJROW" : objectiveName_);
4164   line.append("\nROWS\n N  ");
4165   line.append(objrow);
4166   line.append("\n");
4167   writeString(output, line.c_str());
4168 
4169   // Rows section
4170   // Sense array
4171   // But massage if looks odd
4172   char *sense = new char[numberRows_];
4173   memcpy(sense, getRowSense(), numberRows_);
4174   const double *rowLower = getRowLower();
4175   const double *rowUpper = getRowUpper();
4176 
4177   for (i = 0; i < numberRows_; i++) {
4178     line = " ";
4179     if (sense[i] != 'R') {
4180       line.append(1, sense[i]);
4181     } else {
4182       if (rowLower[i] > -1.0e30) {
4183         if (rowUpper[i] < 1.0e30) {
4184           line.append("L");
4185         } else {
4186           sense[i] = 'G';
4187           line.append(1, sense[i]);
4188         }
4189       } else {
4190         sense[i] = 'L';
4191         line.append(1, sense[i]);
4192       }
4193     }
4194     line.append("  ");
4195     line.append(rowNames[i]);
4196     line.append("\n");
4197     writeString(output, line.c_str());
4198   }
4199 
4200   // COLUMNS card
4201   writeString(output, "COLUMNS\n");
4202 
4203   bool ifBounds = false;
4204   double largeValue = infinity_;
4205   largeValue = 1.0e30; // safer
4206 
4207   const double *columnLower = getColLower();
4208   const double *columnUpper = getColUpper();
4209   const double *objective = getObjCoefficients();
4210   const CoinPackedMatrix *matrix = getMatrixByCol();
4211   const double *elements = matrix->getElements();
4212   const int *rows = matrix->getIndices();
4213   const CoinBigIndex *starts = matrix->getVectorStarts();
4214   const int *lengths = matrix->getVectorLengths();
4215 
4216   char outputValue[2][24];
4217   char outputRow[2][100];
4218   // strings
4219   int nextRowString = numberRows_ + 10;
4220   int nextColumnString = numberColumns_ + 10;
4221   int whichString = 0;
4222   const char *nextString = NULL;
4223   // mark string rows
4224   char *stringRow = new char[numberRows_ + 1];
4225   memset(stringRow, 0, numberRows_ + 1);
4226   if (numberStringElements_) {
4227     decodeString(whichString, nextRowString, nextColumnString, nextString);
4228   }
4229   // Arrays so we can put out rows in order
4230   int *tempRow = new int[numberRows_];
4231   double *tempValue = new double[numberRows_];
4232 
4233   // Through columns (only put out if elements or objective value)
4234   for (i = 0; i < numberColumns_; i++) {
4235     if (i == nextColumnString) {
4236       // set up
4237       int k = whichString;
4238       int iColumn = nextColumnString;
4239       int iRow = nextRowString;
4240       const char *dummy;
4241       while (iColumn == nextColumnString) {
4242         stringRow[iRow] = 1;
4243         k++;
4244         decodeString(k, iRow, iColumn, dummy);
4245       }
4246     }
4247     if (objective[i] || lengths[i] || i == nextColumnString) {
4248       // see if bound will be needed
4249       if (columnLower[i] || columnUpper[i] < largeValue || isInteger(i))
4250         ifBounds = true;
4251       int numberFields = 0;
4252       if (objective[i]) {
4253         convertDouble(0, formatType, objective[i], outputValue[0],
4254           objrow, outputRow[0]);
4255         numberFields = 1;
4256         if (stringRow[numberRows_]) {
4257           assert(objective[i] == STRING_VALUE);
4258           assert(nextColumnString == i && nextRowString == numberRows_);
4259           strcpyeq(outputValue[0], nextString);
4260           stringRow[numberRows_] = 0;
4261           decodeString(++whichString, nextRowString, nextColumnString, nextString);
4262         }
4263       }
4264       if (numberFields == numberAcross) {
4265         // put out card
4266         outputCard(formatType, numberFields,
4267           output, "    ",
4268           columnNames[i],
4269           outputValue,
4270           outputRow);
4271         numberFields = 0;
4272       }
4273       int j;
4274       int numberEntries = lengths[i];
4275       CoinBigIndex start = starts[i];
4276       for (j = 0; j < numberEntries; j++) {
4277         tempRow[j] = rows[start + j];
4278         tempValue[j] = elements[start + j];
4279       }
4280       CoinSort_2(tempRow, tempRow + numberEntries, tempValue);
4281       for (j = 0; j < numberEntries; j++) {
4282         int jRow = tempRow[j];
4283         double value = tempValue[j];
4284         if (value && !stringRow[jRow]) {
4285           convertDouble(0, formatType, value,
4286             outputValue[numberFields],
4287             rowNames[jRow],
4288             outputRow[numberFields]);
4289           numberFields++;
4290           if (numberFields == numberAcross) {
4291             // put out card
4292             outputCard(formatType, numberFields,
4293               output, "    ",
4294               columnNames[i],
4295               outputValue,
4296               outputRow);
4297             numberFields = 0;
4298           }
4299         }
4300       }
4301       if (numberFields) {
4302         // put out card
4303         outputCard(formatType, numberFields,
4304           output, "    ",
4305           columnNames[i],
4306           outputValue,
4307           outputRow);
4308       }
4309     }
4310     // end see if any strings
4311     if (i == nextColumnString) {
4312       int iColumn = nextColumnString;
4313       int iRow = nextRowString;
4314       while (iColumn == nextColumnString) {
4315         double value = 1.0;
4316         convertDouble(0, formatType, value,
4317           outputValue[0],
4318           rowNames[nextRowString],
4319           outputRow[0]);
4320         strcpyeq(outputValue[0], nextString);
4321         // put out card
4322         outputCard(formatType, 1,
4323           output, "    ",
4324           columnNames[i],
4325           outputValue,
4326           outputRow);
4327         stringRow[iRow] = 0;
4328         decodeString(++whichString, nextRowString, nextColumnString, nextString);
4329       }
4330     }
4331   }
4332   delete[] tempRow;
4333   delete[] tempValue;
4334   delete[] stringRow;
4335 
4336   bool ifRange = false;
4337   // RHS
4338   writeString(output, "RHS\n");
4339 
4340   int numberFields = 0;
4341   // If there is any offset - then do that
4342   if (objectiveOffset_) {
4343     convertDouble(1, formatType, objectiveOffset_,
4344       outputValue[0],
4345       objrow,
4346       outputRow[0]);
4347     numberFields++;
4348     if (numberFields == numberAcross) {
4349       // put out card
4350       outputCard(formatType, numberFields,
4351         output, "    ",
4352         "RHS",
4353         outputValue,
4354         outputRow);
4355       numberFields = 0;
4356     }
4357   }
4358   for (i = 0; i < numberRows_; i++) {
4359     double value;
4360     switch (sense[i]) {
4361     case 'E':
4362       value = rowLower[i];
4363       break;
4364     case 'R':
4365       value = rowUpper[i];
4366       ifRange = true;
4367       break;
4368     case 'L':
4369       value = rowUpper[i];
4370       break;
4371     case 'G':
4372       value = rowLower[i];
4373       break;
4374     default:
4375       value = 0.0;
4376       break;
4377     }
4378     if (value != 0.0) {
4379       convertDouble(1, formatType, value,
4380         outputValue[numberFields],
4381         rowNames[i],
4382         outputRow[numberFields]);
4383       if (i == nextRowString && nextColumnString >= numberColumns_) {
4384         strcpyeq(outputValue[0], nextString);
4385         decodeString(++whichString, nextRowString, nextColumnString, nextString);
4386       }
4387       numberFields++;
4388       if (numberFields == numberAcross) {
4389         // put out card
4390         outputCard(formatType, numberFields,
4391           output, "    ",
4392           "RHS",
4393           outputValue,
4394           outputRow);
4395         numberFields = 0;
4396       }
4397     }
4398   }
4399   if (numberFields) {
4400     // put out card
4401     outputCard(formatType, numberFields,
4402       output, "    ",
4403       "RHS",
4404       outputValue,
4405       outputRow);
4406   }
4407 
4408   if (ifRange) {
4409     // RANGES
4410     writeString(output, "RANGES\n");
4411 
4412     numberFields = 0;
4413     for (i = 0; i < numberRows_; i++) {
4414       if (sense[i] == 'R') {
4415         double value = rowUpper[i] - rowLower[i];
4416         if (value < 1.0e30) {
4417           convertDouble(1, formatType, value,
4418             outputValue[numberFields],
4419             rowNames[i],
4420             outputRow[numberFields]);
4421           numberFields++;
4422           if (numberFields == numberAcross) {
4423             // put out card
4424             outputCard(formatType, numberFields,
4425               output, "    ",
4426               "RANGE",
4427               outputValue,
4428               outputRow);
4429             numberFields = 0;
4430           }
4431         }
4432       }
4433     }
4434     if (numberFields) {
4435       // put out card
4436       outputCard(formatType, numberFields,
4437         output, "    ",
4438         "RANGE",
4439         outputValue,
4440         outputRow);
4441     }
4442   }
4443   delete[] sense;
4444   if (ifBounds) {
4445     // BOUNDS
4446     writeString(output, "BOUNDS\n");
4447 
4448     for (i = 0; i < numberColumns_; i++) {
4449       if (i == nextColumnString) {
4450         // just lo and up
4451         if (columnLower[i] == STRING_VALUE) {
4452           assert(nextRowString == numberRows_ + 1);
4453           convertDouble(2, formatType, 1.0,
4454             outputValue[0],
4455             columnNames[i],
4456             outputRow[0]);
4457           strcpyeq(outputValue[0], nextString);
4458           decodeString(++whichString, nextRowString, nextColumnString, nextString);
4459           if (i == nextColumnString) {
4460             assert(columnUpper[i] == STRING_VALUE);
4461             assert(nextRowString == numberRows_ + 2);
4462             if (!strcmp(nextString, outputValue[0])) {
4463               // put out card FX
4464               outputCard(formatType, 1,
4465                 output, " FX ",
4466                 "BOUND",
4467                 outputValue,
4468                 outputRow);
4469             } else {
4470               // put out card LO
4471               outputCard(formatType, 1,
4472                 output, " LO ",
4473                 "BOUND",
4474                 outputValue,
4475                 outputRow);
4476               // put out card UP
4477               strcpyeq(outputValue[0], nextString);
4478               outputCard(formatType, 1,
4479                 output, " UP ",
4480                 "BOUND",
4481                 outputValue,
4482                 outputRow);
4483             }
4484             decodeString(++whichString, nextRowString, nextColumnString, nextString);
4485           } else {
4486             // just LO
4487             // put out card LO
4488             outputCard(formatType, 1,
4489               output, " LO ",
4490               "BOUND",
4491               outputValue,
4492               outputRow);
4493           }
4494         } else if (columnUpper[i] == STRING_VALUE) {
4495           assert(nextRowString == numberRows_ + 2);
4496           convertDouble(2, formatType, 1.0,
4497             outputValue[0],
4498             columnNames[i],
4499             outputRow[0]);
4500           strcpyeq(outputValue[0], nextString);
4501           outputCard(formatType, 1,
4502             output, " UP ",
4503             "BOUND",
4504             outputValue,
4505             outputRow);
4506           decodeString(++whichString, nextRowString, nextColumnString, nextString);
4507         }
4508         continue;
4509       }
4510       if (objective[i] || lengths[i]) {
4511         // see if bound will be needed
4512         if (columnLower[i] || columnUpper[i] < largeValue || isInteger(i)) {
4513           double lowerValue = columnLower[i];
4514           double upperValue = columnUpper[i];
4515           if (isInteger(i)) {
4516             // Old argument - what are correct ranges for integer variables
4517             lowerValue = CoinMax(lowerValue, -MAX_INTEGER);
4518             upperValue = CoinMin(upperValue, MAX_INTEGER);
4519           }
4520           int numberFields = 1;
4521           std::string header[2];
4522           double value[2];
4523           if (lowerValue <= -largeValue) {
4524             // FR or MI
4525             if (upperValue >= largeValue && !isInteger(i)) {
4526               header[0] = " FR ";
4527               value[0] = largeValue;
4528             } else {
4529               header[0] = " MI ";
4530               value[0] = -largeValue;
4531               if (!isInteger(i))
4532                 header[1] = " UP ";
4533               else
4534                 header[1] = " UI ";
4535               if (upperValue < largeValue)
4536                 value[1] = upperValue;
4537               else
4538                 value[1] = largeValue;
4539               numberFields = 2;
4540             }
4541           } else if (fabs(upperValue - lowerValue) < 1.0e-8) {
4542             header[0] = " FX ";
4543             value[0] = lowerValue;
4544           } else {
4545             // do LO if needed
4546             if (lowerValue || isIntegerOrSemiContinuous(i) > 2) {
4547               // LO
4548               header[0] = " LO ";
4549               value[0] = lowerValue;
4550               if (isIntegerOrSemiContinuous(i) > 2) {
4551                 if (lowerValue) {
4552                   if (isIntegerOrSemiContinuous(i) == 4)
4553                     header[0] = " LI ";
4554                   numberFields = 2;
4555                 }
4556                 header[numberFields - 1] = " SC ";
4557                 if (upperValue < largeValue)
4558                   value[numberFields - 1] = upperValue;
4559                 else
4560                   value[numberFields - 1] = largeValue;
4561               } else if (isInteger(i)) {
4562                 // Integer variable so UI
4563                 header[1] = " UI ";
4564                 if (upperValue < largeValue)
4565                   value[1] = upperValue;
4566                 else
4567                   value[1] = largeValue;
4568                 numberFields = 2;
4569               } else if (upperValue < largeValue) {
4570                 // UP
4571                 header[1] = " UP ";
4572                 value[1] = upperValue;
4573                 numberFields = 2;
4574               }
4575             } else {
4576               if (isInteger(i)) {
4577                 // Integer variable so BV or UI
4578                 if (fabs(upperValue - 1.0) < 1.0e-8) {
4579                   // BV
4580                   header[0] = " BV ";
4581                   value[0] = 1.0;
4582                 } else {
4583                   // UI
4584                   header[0] = " UI ";
4585                   if (upperValue < largeValue)
4586                     value[0] = upperValue;
4587                   else
4588                     value[0] = largeValue;
4589                 }
4590               } else {
4591                 // UP
4592                 header[0] = " UP ";
4593                 value[0] = upperValue;
4594               }
4595             }
4596           }
4597           // put out fields
4598           int j;
4599           for (j = 0; j < numberFields; j++) {
4600             convertDouble(2, formatType, value[j],
4601               outputValue[0],
4602               columnNames[i],
4603               outputRow[0]);
4604             // put out card
4605             outputCard(formatType, 1,
4606               output, header[j],
4607               "BOUND",
4608               outputValue,
4609               outputRow);
4610           }
4611         }
4612       }
4613     }
4614   }
4615 
4616   // do any quadratic part
4617   if (quadratic) {
4618 
4619     writeString(output, "QUADOBJ\n");
4620 
4621     const int *columnQuadratic = quadratic->getIndices();
4622     const CoinBigIndex *columnQuadraticStart = quadratic->getVectorStarts();
4623     const int *columnQuadraticLength = quadratic->getVectorLengths();
4624     const double *quadraticElement = quadratic->getElements();
4625     for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
4626       int numberFields = 0;
4627       for (CoinBigIndex j = columnQuadraticStart[iColumn];
4628            j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) {
4629         int jColumn = columnQuadratic[j];
4630         double elementValue = quadraticElement[j];
4631         convertDouble(0, formatType, elementValue,
4632           outputValue[numberFields],
4633           columnNames[jColumn],
4634           outputRow[numberFields]);
4635         numberFields++;
4636         if (numberFields == numberAcross) {
4637           // put out card
4638           outputCard(formatType, numberFields,
4639             output, "    ",
4640             columnNames[iColumn],
4641             outputValue,
4642             outputRow);
4643           numberFields = 0;
4644         }
4645       }
4646       if (numberFields) {
4647         // put out card
4648         outputCard(formatType, numberFields,
4649           output, "    ",
4650           columnNames[iColumn],
4651           outputValue,
4652           outputRow);
4653       }
4654     }
4655   }
4656   // SOS
4657   if (numberSOS) {
4658     writeString(output, "SOS\n");
4659     for (int i = 0; i < numberSOS; i++) {
4660       int type = setInfo[i].setType();
4661       writeString(output, (type == 1) ? " S1\n" : " S2\n");
4662       int n = setInfo[i].numberEntries();
4663       const int *which = setInfo[i].which();
4664       const double *weights = setInfo[i].weights();
4665 
4666       for (int j = 0; j < n; j++) {
4667         int k = which[j];
4668         convertDouble(2, formatType,
4669           weights ? weights[j] : COIN_DBL_MAX, outputValue[0],
4670           "", outputRow[0]);
4671         // put out card
4672         outputCard(formatType, 1,
4673           output, "   ",
4674           columnNames[k],
4675           outputValue, outputRow);
4676       }
4677     }
4678   }
4679 
4680   // and finish
4681 
4682   writeString(output, "ENDATA\n");
4683 
4684   free(objrow);
4685 
4686   delete output;
4687   setlocale(LC_ALL, saveLocale);
4688   free(saveLocale);
4689   return 0;
4690 }
4691 
4692 //------------------------------------------------------------------
4693 // Problem name
getProblemName() const4694 const char *CoinMpsIO::getProblemName() const
4695 {
4696   return problemName_;
4697 }
4698 // Objective name
getObjectiveName() const4699 const char *CoinMpsIO::getObjectiveName() const
4700 {
4701   return objectiveName_;
4702 }
4703 // Rhs name
getRhsName() const4704 const char *CoinMpsIO::getRhsName() const
4705 {
4706   return rhsName_;
4707 }
4708 // Range name
getRangeName() const4709 const char *CoinMpsIO::getRangeName() const
4710 {
4711   return rangeName_;
4712 }
4713 // Bound name
getBoundName() const4714 const char *CoinMpsIO::getBoundName() const
4715 {
4716   return boundName_;
4717 }
4718 
4719 //------------------------------------------------------------------
4720 // Get number of rows, columns and elements
4721 //------------------------------------------------------------------
getNumCols() const4722 int CoinMpsIO::getNumCols() const
4723 {
4724   return numberColumns_;
4725 }
getNumRows() const4726 int CoinMpsIO::getNumRows() const
4727 {
4728   return numberRows_;
4729 }
getNumElements() const4730 CoinBigIndex CoinMpsIO::getNumElements() const
4731 {
4732   return numberElements_;
4733 }
4734 
4735 //------------------------------------------------------------------
4736 // Get pointer to column lower and upper bounds.
4737 //------------------------------------------------------------------
getColLower() const4738 const double *CoinMpsIO::getColLower() const
4739 {
4740   return collower_;
4741 }
getColUpper() const4742 const double *CoinMpsIO::getColUpper() const
4743 {
4744   return colupper_;
4745 }
4746 
4747 //------------------------------------------------------------------
4748 // Get pointer to row lower and upper bounds.
4749 //------------------------------------------------------------------
getRowLower() const4750 const double *CoinMpsIO::getRowLower() const
4751 {
4752   return rowlower_;
4753 }
getRowUpper() const4754 const double *CoinMpsIO::getRowUpper() const
4755 {
4756   return rowupper_;
4757 }
4758 
4759 /** A quick inlined function to convert from lb/ub style constraint
4760     definition to sense/rhs/range style */
4761 inline void
convertBoundToSense(const double lower,const double upper,char & sense,double & right,double & range) const4762 CoinMpsIO::convertBoundToSense(const double lower, const double upper,
4763   char &sense, double &right,
4764   double &range) const
4765 {
4766   range = 0.0;
4767   if (lower > -infinity_) {
4768     if (upper < infinity_) {
4769       right = upper;
4770       if (upper == lower) {
4771         sense = 'E';
4772       } else {
4773         sense = 'R';
4774         range = upper - lower;
4775       }
4776     } else {
4777       sense = 'G';
4778       right = lower;
4779     }
4780   } else {
4781     if (upper < infinity_) {
4782       sense = 'L';
4783       right = upper;
4784     } else {
4785       sense = 'N';
4786       right = 0.0;
4787     }
4788   }
4789 }
4790 
4791 //-----------------------------------------------------------------------------
4792 /** A quick inlined function to convert from sense/rhs/range stryle constraint
4793     definition to lb/ub style */
4794 inline void
convertSenseToBound(const char sense,const double right,const double range,double & lower,double & upper) const4795 CoinMpsIO::convertSenseToBound(const char sense, const double right,
4796   const double range,
4797   double &lower, double &upper) const
4798 {
4799   switch (sense) {
4800   case 'E':
4801     lower = upper = right;
4802     break;
4803   case 'L':
4804     lower = -infinity_;
4805     upper = right;
4806     break;
4807   case 'G':
4808     lower = right;
4809     upper = infinity_;
4810     break;
4811   case 'R':
4812     lower = right - range;
4813     upper = right;
4814     break;
4815   case 'N':
4816     lower = -infinity_;
4817     upper = infinity_;
4818     break;
4819   }
4820 }
4821 //------------------------------------------------------------------
4822 // Get sense of row constraints.
4823 //------------------------------------------------------------------
getRowSense() const4824 const char *CoinMpsIO::getRowSense() const
4825 {
4826   if (rowsense_ == NULL) {
4827 
4828     int nr = numberRows_;
4829     rowsense_ = reinterpret_cast< char * >(malloc(nr * sizeof(char)));
4830 
4831     double dum1, dum2;
4832     int i;
4833     for (i = 0; i < nr; i++) {
4834       convertBoundToSense(rowlower_[i], rowupper_[i], rowsense_[i], dum1, dum2);
4835     }
4836   }
4837   return rowsense_;
4838 }
4839 
4840 //------------------------------------------------------------------
4841 // Get the rhs of rows.
4842 //------------------------------------------------------------------
getRightHandSide() const4843 const double *CoinMpsIO::getRightHandSide() const
4844 {
4845   if (rhs_ == NULL) {
4846 
4847     int nr = numberRows_;
4848     rhs_ = reinterpret_cast< double * >(malloc(nr * sizeof(double)));
4849 
4850     char dum1;
4851     double dum2;
4852     int i;
4853     for (i = 0; i < nr; i++) {
4854       convertBoundToSense(rowlower_[i], rowupper_[i], dum1, rhs_[i], dum2);
4855     }
4856   }
4857   return rhs_;
4858 }
4859 
4860 //------------------------------------------------------------------
4861 // Get the range of rows.
4862 // Length of returned vector is getNumRows();
4863 //------------------------------------------------------------------
getRowRange() const4864 const double *CoinMpsIO::getRowRange() const
4865 {
4866   if (rowrange_ == NULL) {
4867 
4868     int nr = numberRows_;
4869     rowrange_ = reinterpret_cast< double * >(malloc(nr * sizeof(double)));
4870     std::fill(rowrange_, rowrange_ + nr, 0.0);
4871 
4872     char dum1;
4873     double dum2;
4874     int i;
4875     for (i = 0; i < nr; i++) {
4876       convertBoundToSense(rowlower_[i], rowupper_[i], dum1, dum2, rowrange_[i]);
4877     }
4878   }
4879   return rowrange_;
4880 }
4881 
getObjCoefficients() const4882 const double *CoinMpsIO::getObjCoefficients() const
4883 {
4884   return objective_;
4885 }
4886 
4887 //------------------------------------------------------------------
4888 // Create a row copy of the matrix ...
4889 //------------------------------------------------------------------
getMatrixByRow() const4890 const CoinPackedMatrix *CoinMpsIO::getMatrixByRow() const
4891 {
4892   if (matrixByRow_ == NULL && matrixByColumn_) {
4893     matrixByRow_ = new CoinPackedMatrix(*matrixByColumn_);
4894     matrixByRow_->reverseOrdering();
4895   }
4896   return matrixByRow_;
4897 }
4898 
4899 //------------------------------------------------------------------
4900 // Create a column copy of the matrix ...
4901 //------------------------------------------------------------------
getMatrixByCol() const4902 const CoinPackedMatrix *CoinMpsIO::getMatrixByCol() const
4903 {
4904   return matrixByColumn_;
4905 }
4906 
4907 //------------------------------------------------------------------
4908 // Save the data ...
4909 //------------------------------------------------------------------
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)4910 void CoinMpsIO::setMpsDataWithoutRowAndColNames(
4911   const CoinPackedMatrix &m, const double infinity,
4912   const double *collb, const double *colub,
4913   const double *obj, const char *integrality,
4914   const double *rowlb, const double *rowub)
4915 {
4916   freeAll();
4917   if (m.isColOrdered()) {
4918     matrixByColumn_ = new CoinPackedMatrix(m);
4919   } else {
4920     matrixByColumn_ = new CoinPackedMatrix;
4921     matrixByColumn_->reverseOrderedCopyOf(m);
4922   }
4923   numberColumns_ = matrixByColumn_->getNumCols();
4924   numberRows_ = matrixByColumn_->getNumRows();
4925   numberElements_ = matrixByColumn_->getNumElements();
4926   defaultBound_ = 1;
4927   infinity_ = infinity;
4928   objectiveOffset_ = 0;
4929 
4930   rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
4931   rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
4932   collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
4933   colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
4934   objective_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
4935   std::copy(rowlb, rowlb + numberRows_, rowlower_);
4936   std::copy(rowub, rowub + numberRows_, rowupper_);
4937   std::copy(collb, collb + numberColumns_, collower_);
4938   std::copy(colub, colub + numberColumns_, colupper_);
4939   std::copy(obj, obj + numberColumns_, objective_);
4940   if (integrality) {
4941     integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
4942     std::copy(integrality, integrality + numberColumns_, integerType_);
4943   } else {
4944     integerType_ = NULL;
4945   }
4946 
4947   problemName_ = CoinStrdup("");
4948   objectiveName_ = CoinStrdup("");
4949   rhsName_ = CoinStrdup("");
4950   rangeName_ = CoinStrdup("");
4951   boundName_ = CoinStrdup("");
4952 }
4953 
setMpsDataColAndRowNames(char const * const * const colnames,char const * const * const rownames)4954 void CoinMpsIO::setMpsDataColAndRowNames(
4955   char const *const *const colnames,
4956   char const *const *const rownames)
4957 {
4958   releaseRowNames();
4959   releaseColumnNames();
4960   // If long names free format
4961   names_[0] = reinterpret_cast< char ** >(malloc(numberRows_ * sizeof(char *)));
4962   names_[1] = reinterpret_cast< char ** >(malloc(numberColumns_ * sizeof(char *)));
4963   numberHash_[0] = numberRows_;
4964   numberHash_[1] = numberColumns_;
4965   char **rowNames = names_[0];
4966   char **columnNames = names_[1];
4967   int i;
4968   // so we can adjust for long names
4969   int lengthMalloc = 9;
4970   int maxIndex = 10000000;
4971   if (rownames) {
4972     for (i = 0; i < numberRows_; ++i) {
4973       if (i == maxIndex) {
4974         lengthMalloc++;
4975         maxIndex *= 10;
4976       }
4977       if (rownames[i]) {
4978         rowNames[i] = CoinStrdup(rownames[i]);
4979       } else {
4980         rowNames[i] = reinterpret_cast< char * >(malloc(lengthMalloc * sizeof(char)));
4981         sprintf(rowNames[i], "R%7.7d", i);
4982       }
4983     }
4984   } else {
4985     for (i = 0; i < numberRows_; ++i) {
4986       if (i == maxIndex) {
4987         lengthMalloc++;
4988         maxIndex *= 10;
4989       }
4990       rowNames[i] = reinterpret_cast< char * >(malloc(lengthMalloc * sizeof(char)));
4991       sprintf(rowNames[i], "R%7.7d", i);
4992     }
4993   }
4994 #ifndef NONAMES
4995   lengthMalloc = 9;
4996   maxIndex = 10000000;
4997   if (colnames) {
4998     for (i = 0; i < numberColumns_; ++i) {
4999       if (i == maxIndex) {
5000         lengthMalloc++;
5001         maxIndex *= 10;
5002       }
5003       if (colnames[i]) {
5004         columnNames[i] = CoinStrdup(colnames[i]);
5005       } else {
5006         columnNames[i] = reinterpret_cast< char * >(malloc(lengthMalloc * sizeof(char)));
5007         sprintf(columnNames[i], "C%7.7d", i);
5008       }
5009     }
5010   } else {
5011     for (i = 0; i < numberColumns_; ++i) {
5012       if (i == maxIndex) {
5013         lengthMalloc++;
5014         maxIndex *= 10;
5015       }
5016       columnNames[i] = reinterpret_cast< char * >(malloc(lengthMalloc * sizeof(char)));
5017       sprintf(columnNames[i], "C%7.7d", i);
5018     }
5019   }
5020 #else
5021   const double *objective = getObjCoefficients();
5022   const CoinPackedMatrix *matrix = getMatrixByCol();
5023   const int *lengths = matrix->getVectorLengths();
5024   int k = 0;
5025   for (i = 0; i < numberColumns_; ++i) {
5026     columnNames[i] = reinterpret_cast< char * >(malloc(9 * sizeof(char)));
5027     sprintf(columnNames[i], "C%7.7d", k);
5028     if (objective[i] || lengths[i])
5029       k++;
5030   }
5031 #endif
5032 }
5033 
setMpsDataColAndRowNames(const std::vector<std::string> & colnames,const std::vector<std::string> & rownames)5034 void CoinMpsIO::setMpsDataColAndRowNames(
5035   const std::vector< std::string > &colnames,
5036   const std::vector< std::string > &rownames)
5037 {
5038   // If long names free format
5039   names_[0] = reinterpret_cast< char ** >(malloc(numberRows_ * sizeof(char *)));
5040   names_[1] = reinterpret_cast< char ** >(malloc(numberColumns_ * sizeof(char *)));
5041   char **rowNames = names_[0];
5042   char **columnNames = names_[1];
5043   int i;
5044   if (rownames.size() != 0) {
5045     for (i = 0; i < numberRows_; ++i) {
5046       rowNames[i] = CoinStrdup(rownames[i].c_str());
5047     }
5048   } else {
5049     // so we can adjust for long names
5050     int lengthMalloc = 9;
5051     int maxIndex = 10000000;
5052     for (i = 0; i < numberRows_; ++i) {
5053       if (i == maxIndex) {
5054         lengthMalloc++;
5055         maxIndex *= 10;
5056       }
5057       rowNames[i] = reinterpret_cast< char * >(malloc(lengthMalloc * sizeof(char)));
5058       sprintf(rowNames[i], "R%7.7d", i);
5059     }
5060   }
5061   if (colnames.size() != 0) {
5062     for (i = 0; i < numberColumns_; ++i) {
5063       columnNames[i] = CoinStrdup(colnames[i].c_str());
5064     }
5065   } else {
5066     // so we can adjust for long names
5067     int lengthMalloc = 9;
5068     int maxIndex = 10000000;
5069     for (i = 0; i < numberColumns_; ++i) {
5070       if (i == maxIndex) {
5071         lengthMalloc++;
5072         maxIndex *= 10;
5073       }
5074       columnNames[i] = reinterpret_cast< char * >(malloc(lengthMalloc * sizeof(char)));
5075       sprintf(columnNames[i], "C%7.7d", i);
5076     }
5077   }
5078 }
5079 
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)5080 void CoinMpsIO::setMpsData(const CoinPackedMatrix &m, const double infinity,
5081   const double *collb, const double *colub,
5082   const double *obj, const char *integrality,
5083   const double *rowlb, const double *rowub,
5084   char const *const *const colnames,
5085   char const *const *const rownames)
5086 {
5087   setMpsDataWithoutRowAndColNames(m, infinity, collb, colub, obj, integrality, rowlb, rowub);
5088   setMpsDataColAndRowNames(colnames, rownames);
5089 }
5090 
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<std::string> & colnames,const std::vector<std::string> & rownames)5091 void CoinMpsIO::setMpsData(const CoinPackedMatrix &m, const double infinity,
5092   const double *collb, const double *colub,
5093   const double *obj, const char *integrality,
5094   const double *rowlb, const double *rowub,
5095   const std::vector< std::string > &colnames,
5096   const std::vector< std::string > &rownames)
5097 {
5098   setMpsDataWithoutRowAndColNames(m, infinity, collb, colub, obj, integrality, rowlb, rowub);
5099   setMpsDataColAndRowNames(colnames, rownames);
5100 }
5101 
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)5102 void CoinMpsIO::setMpsData(const CoinPackedMatrix &m, const double infinity,
5103   const double *collb, const double *colub,
5104   const double *obj, const char *integrality,
5105   const char *rowsen, const double *rowrhs,
5106   const double *rowrng,
5107   char const *const *const colnames,
5108   char const *const *const rownames)
5109 {
5110   const int numrows = m.getNumRows();
5111 
5112   double *rlb = numrows ? new double[numrows] : 0;
5113   double *rub = numrows ? new double[numrows] : 0;
5114 
5115   for (int i = 0; i < numrows; ++i) {
5116     convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]);
5117   }
5118   setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub,
5119     colnames, rownames);
5120   delete[] rlb;
5121   delete[] rub;
5122 }
5123 
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<std::string> & colnames,const std::vector<std::string> & rownames)5124 void CoinMpsIO::setMpsData(const CoinPackedMatrix &m, const double infinity,
5125   const double *collb, const double *colub,
5126   const double *obj, const char *integrality,
5127   const char *rowsen, const double *rowrhs,
5128   const double *rowrng,
5129   const std::vector< std::string > &colnames,
5130   const std::vector< std::string > &rownames)
5131 {
5132   const int numrows = m.getNumRows();
5133 
5134   double *rlb = numrows ? new double[numrows] : 0;
5135   double *rub = numrows ? new double[numrows] : 0;
5136 
5137   for (int i = 0; i < numrows; ++i) {
5138     convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]);
5139   }
5140   setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub,
5141     colnames, rownames);
5142   delete[] rlb;
5143   delete[] rub;
5144 }
5145 
setProblemName(const char * name)5146 void CoinMpsIO::setProblemName(const char *name)
5147 {
5148   free(problemName_);
5149   problemName_ = CoinStrdup(name);
5150 }
5151 
setObjectiveName(const char * name)5152 void CoinMpsIO::setObjectiveName(const char *name)
5153 {
5154   free(objectiveName_);
5155   objectiveName_ = CoinStrdup(name);
5156 }
5157 
5158 //------------------------------------------------------------------
5159 // Return true if column is a continuous, binary, ...
5160 //------------------------------------------------------------------
isContinuous(int columnNumber) const5161 bool CoinMpsIO::isContinuous(int columnNumber) const
5162 {
5163   const char *intType = integerType_;
5164   if (intType == NULL)
5165     return true;
5166   assert(columnNumber >= 0 && columnNumber < numberColumns_);
5167   if (intType[columnNumber] == 0)
5168     return true;
5169   return false;
5170 }
5171 
5172 /* Return true if column is integer.
5173    Note: This function returns true if the the column
5174    is binary or a general integer.
5175 */
isInteger(int columnNumber) const5176 bool CoinMpsIO::isInteger(int columnNumber) const
5177 {
5178   const char *intType = integerType_;
5179   if (intType == NULL)
5180     return false;
5181   assert(columnNumber >= 0 && columnNumber < numberColumns_);
5182   if (intType[columnNumber] != 0)
5183     return true;
5184   return false;
5185 }
5186 /* Return 1 if column is integer, 2 if optional,
5187    3 if semi-continuous, 4 if semi-continous integer.
5188    Note: This function returns 1 if the column
5189    is binary or a general integer.
5190 */
isIntegerOrSemiContinuous(int columnNumber) const5191 int CoinMpsIO::isIntegerOrSemiContinuous(int columnNumber) const
5192 {
5193   const char *intType = integerType_;
5194   if (intType == NULL)
5195     return false;
5196   assert(columnNumber >= 0 && columnNumber < numberColumns_);
5197   return intType[columnNumber];
5198 }
5199 // if integer
integerColumns() const5200 const char *CoinMpsIO::integerColumns() const
5201 {
5202   return integerType_;
5203 }
5204 // Pass in array saying if each variable integer
copyInIntegerInformation(const char * integerType)5205 void CoinMpsIO::copyInIntegerInformation(const char *integerType)
5206 {
5207   if (integerType) {
5208     if (!integerType_)
5209       integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
5210     memcpy(integerType_, integerType, numberColumns_);
5211   } else {
5212     free(integerType_);
5213     integerType_ = NULL;
5214   }
5215 }
5216 // names - returns NULL if out of range
rowName(int index) const5217 const char *CoinMpsIO::rowName(int index) const
5218 {
5219   if (index >= 0 && index < numberRows_) {
5220     return names_[0][index];
5221   } else {
5222     return NULL;
5223   }
5224 }
columnName(int index) const5225 const char *CoinMpsIO::columnName(int index) const
5226 {
5227   if (index >= 0 && index < numberColumns_) {
5228     return names_[1][index];
5229   } else {
5230     return NULL;
5231   }
5232 }
5233 // names - returns -1 if name not found
rowIndex(const char * name) const5234 int CoinMpsIO::rowIndex(const char *name) const
5235 {
5236   if (!hash_[0]) {
5237     if (numberRows_) {
5238       startHash(0);
5239     } else {
5240       return -1;
5241     }
5242   }
5243   return findHash(name, 0);
5244 }
columnIndex(const char * name) const5245 int CoinMpsIO::columnIndex(const char *name) const
5246 {
5247   if (!hash_[1]) {
5248     if (numberColumns_) {
5249       startHash(1);
5250     } else {
5251       return -1;
5252     }
5253   }
5254   return findHash(name, 1);
5255 }
5256 
5257 // Release all row information (lower, upper)
releaseRowInformation()5258 void CoinMpsIO::releaseRowInformation()
5259 {
5260   free(rowlower_);
5261   free(rowupper_);
5262   rowlower_ = NULL;
5263   rowupper_ = NULL;
5264 }
5265 // Release all column information (lower, upper, objective)
releaseColumnInformation()5266 void CoinMpsIO::releaseColumnInformation()
5267 {
5268   free(collower_);
5269   free(colupper_);
5270   free(objective_);
5271   collower_ = NULL;
5272   colupper_ = NULL;
5273   objective_ = NULL;
5274 }
5275 // Release integer information
releaseIntegerInformation()5276 void CoinMpsIO::releaseIntegerInformation()
5277 {
5278   free(integerType_);
5279   integerType_ = NULL;
5280 }
5281 // Release row names
releaseRowNames()5282 void CoinMpsIO::releaseRowNames()
5283 {
5284   releaseRedundantInformation();
5285   int i;
5286   for (i = 0; i < numberHash_[0]; i++) {
5287     free(names_[0][i]);
5288   }
5289   free(names_[0]);
5290   names_[0] = NULL;
5291   numberHash_[0] = 0;
5292 }
5293 // Release column names
releaseColumnNames()5294 void CoinMpsIO::releaseColumnNames()
5295 {
5296   releaseRedundantInformation();
5297   int i;
5298   for (i = 0; i < numberHash_[1]; i++) {
5299     free(names_[1][i]);
5300   }
5301   free(names_[1]);
5302   names_[1] = NULL;
5303   numberHash_[1] = 0;
5304 }
5305 // Release matrix information
releaseMatrixInformation()5306 void CoinMpsIO::releaseMatrixInformation()
5307 {
5308   releaseRedundantInformation();
5309   delete matrixByColumn_;
5310   matrixByColumn_ = NULL;
5311 }
5312 
5313 //-------------------------------------------------------------------
5314 // Default Constructor
5315 //-------------------------------------------------------------------
CoinMpsIO()5316 CoinMpsIO::CoinMpsIO()
5317   : problemName_(CoinStrdup(""))
5318   , objectiveName_(CoinStrdup(""))
5319   , rhsName_(CoinStrdup(""))
5320   , rangeName_(CoinStrdup(""))
5321   , boundName_(CoinStrdup(""))
5322   , numberRows_(0)
5323   , numberColumns_(0)
5324   , numberElements_(0)
5325   , rowsense_(NULL)
5326   , rhs_(NULL)
5327   , rowrange_(NULL)
5328   , matrixByRow_(NULL)
5329   , matrixByColumn_(NULL)
5330   , rowlower_(NULL)
5331   , rowupper_(NULL)
5332   , collower_(NULL)
5333   , colupper_(NULL)
5334   , objective_(NULL)
5335   , objectiveOffset_(0.0)
5336   , integerType_(NULL)
5337   , fileName_(CoinStrdup("????"))
5338   , defaultBound_(1)
5339   , infinity_(COIN_DBL_MAX)
5340   , smallElement_(1.0e-14)
5341   , defaultHandler_(true)
5342   , cardReader_(NULL)
5343   , convertObjective_(false)
5344   , allowStringElements_(0)
5345   , maximumStringElements_(0)
5346   , numberStringElements_(0)
5347   , stringElements_(NULL)
5348 {
5349   numberHash_[0] = 0;
5350   hash_[0] = NULL;
5351   names_[0] = NULL;
5352   numberHash_[1] = 0;
5353   hash_[1] = NULL;
5354   names_[1] = NULL;
5355   handler_ = new CoinMessageHandler();
5356   messages_ = CoinMessage();
5357 }
5358 
5359 //-------------------------------------------------------------------
5360 // Copy constructor
5361 //-------------------------------------------------------------------
CoinMpsIO(const CoinMpsIO & rhs)5362 CoinMpsIO::CoinMpsIO(const CoinMpsIO &rhs)
5363   : problemName_(CoinStrdup(""))
5364   , objectiveName_(CoinStrdup(""))
5365   , rhsName_(CoinStrdup(""))
5366   , rangeName_(CoinStrdup(""))
5367   , boundName_(CoinStrdup(""))
5368   , numberRows_(0)
5369   , numberColumns_(0)
5370   , numberElements_(0)
5371   , rowsense_(NULL)
5372   , rhs_(NULL)
5373   , rowrange_(NULL)
5374   , matrixByRow_(NULL)
5375   , matrixByColumn_(NULL)
5376   , rowlower_(NULL)
5377   , rowupper_(NULL)
5378   , collower_(NULL)
5379   , colupper_(NULL)
5380   , objective_(NULL)
5381   , objectiveOffset_(0.0)
5382   , integerType_(NULL)
5383   , fileName_(CoinStrdup("????"))
5384   , defaultBound_(1)
5385   , infinity_(COIN_DBL_MAX)
5386   , smallElement_(1.0e-14)
5387   , defaultHandler_(true)
5388   , cardReader_(NULL)
5389   , allowStringElements_(rhs.allowStringElements_)
5390   , maximumStringElements_(rhs.maximumStringElements_)
5391   , numberStringElements_(rhs.numberStringElements_)
5392   , stringElements_(NULL)
5393 {
5394   numberHash_[0] = 0;
5395   hash_[0] = NULL;
5396   names_[0] = NULL;
5397   numberHash_[1] = 0;
5398   hash_[1] = NULL;
5399   names_[1] = NULL;
5400   if (rhs.rowlower_ != NULL || rhs.collower_ != NULL) {
5401     gutsOfCopy(rhs);
5402     // OK and proper to leave rowsense_, rhs_, and
5403     // rowrange_ (also row copy and hash) to NULL.  They will be constructed
5404     // if they are required.
5405   }
5406   defaultHandler_ = rhs.defaultHandler_;
5407   if (defaultHandler_)
5408     handler_ = new CoinMessageHandler(*rhs.handler_);
5409   else
5410     handler_ = rhs.handler_;
5411   messages_ = CoinMessage();
5412 }
5413 
gutsOfCopy(const CoinMpsIO & rhs)5414 void CoinMpsIO::gutsOfCopy(const CoinMpsIO &rhs)
5415 {
5416   defaultHandler_ = rhs.defaultHandler_;
5417   if (rhs.matrixByColumn_)
5418     matrixByColumn_ = new CoinPackedMatrix(*(rhs.matrixByColumn_));
5419   numberElements_ = rhs.numberElements_;
5420   numberRows_ = rhs.numberRows_;
5421   numberColumns_ = rhs.numberColumns_;
5422   convertObjective_ = rhs.convertObjective_;
5423   if (rhs.rowlower_) {
5424     rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
5425     rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
5426     memcpy(rowlower_, rhs.rowlower_, numberRows_ * sizeof(double));
5427     memcpy(rowupper_, rhs.rowupper_, numberRows_ * sizeof(double));
5428   }
5429   if (rhs.collower_) {
5430     collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
5431     colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
5432     objective_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
5433     memcpy(collower_, rhs.collower_, numberColumns_ * sizeof(double));
5434     memcpy(colupper_, rhs.colupper_, numberColumns_ * sizeof(double));
5435     memcpy(objective_, rhs.objective_, numberColumns_ * sizeof(double));
5436   }
5437   if (rhs.integerType_) {
5438     integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
5439     memcpy(integerType_, rhs.integerType_, numberColumns_ * sizeof(char));
5440   }
5441   free(fileName_);
5442   free(problemName_);
5443   free(objectiveName_);
5444   free(rhsName_);
5445   free(rangeName_);
5446   free(boundName_);
5447   fileName_ = CoinStrdup(rhs.fileName_);
5448   problemName_ = CoinStrdup(rhs.problemName_);
5449   objectiveName_ = CoinStrdup(rhs.objectiveName_);
5450   rhsName_ = CoinStrdup(rhs.rhsName_);
5451   rangeName_ = CoinStrdup(rhs.rangeName_);
5452   boundName_ = CoinStrdup(rhs.boundName_);
5453   numberHash_[0] = rhs.numberHash_[0];
5454   numberHash_[1] = rhs.numberHash_[1];
5455   defaultBound_ = rhs.defaultBound_;
5456   infinity_ = rhs.infinity_;
5457   smallElement_ = rhs.smallElement_;
5458   objectiveOffset_ = rhs.objectiveOffset_;
5459   int section;
5460   for (section = 0; section < 2; section++) {
5461     if (numberHash_[section]) {
5462       char **names2 = rhs.names_[section];
5463       names_[section] = reinterpret_cast< char ** >(malloc(numberHash_[section] * sizeof(char *)));
5464       char **names = names_[section];
5465       int i;
5466       for (i = 0; i < numberHash_[section]; i++) {
5467         names[i] = CoinStrdup(names2[i]);
5468       }
5469     }
5470   }
5471   allowStringElements_ = rhs.allowStringElements_;
5472   maximumStringElements_ = rhs.maximumStringElements_;
5473   numberStringElements_ = rhs.numberStringElements_;
5474   if (numberStringElements_) {
5475     stringElements_ = new char *[maximumStringElements_];
5476     for (int i = 0; i < numberStringElements_; i++)
5477       stringElements_[i] = CoinStrdup(rhs.stringElements_[i]);
5478   } else {
5479     stringElements_ = NULL;
5480   }
5481 }
5482 
5483 //-------------------------------------------------------------------
5484 // Destructor
5485 //-------------------------------------------------------------------
~CoinMpsIO()5486 CoinMpsIO::~CoinMpsIO()
5487 {
5488   gutsOfDestructor();
5489 }
5490 
5491 //----------------------------------------------------------------
5492 // Assignment operator
5493 //-------------------------------------------------------------------
5494 CoinMpsIO &
operator =(const CoinMpsIO & rhs)5495 CoinMpsIO::operator=(const CoinMpsIO &rhs)
5496 {
5497   if (this != &rhs) {
5498     gutsOfDestructor();
5499     if (rhs.rowlower_ != NULL || rhs.collower_ != NULL) {
5500       gutsOfCopy(rhs);
5501     }
5502     defaultHandler_ = rhs.defaultHandler_;
5503     if (defaultHandler_)
5504       handler_ = new CoinMessageHandler(*rhs.handler_);
5505     else
5506       handler_ = rhs.handler_;
5507     messages_ = CoinMessage();
5508   }
5509   return *this;
5510 }
5511 
5512 //-------------------------------------------------------------------
gutsOfDestructor()5513 void CoinMpsIO::gutsOfDestructor()
5514 {
5515   freeAll();
5516   if (defaultHandler_) {
5517     delete handler_;
5518     handler_ = NULL;
5519   }
5520   delete cardReader_;
5521   cardReader_ = NULL;
5522 }
5523 
freeAll()5524 void CoinMpsIO::freeAll()
5525 {
5526   releaseRedundantInformation();
5527   releaseRowNames();
5528   releaseColumnNames();
5529   delete matrixByRow_;
5530   delete matrixByColumn_;
5531   matrixByRow_ = NULL;
5532   matrixByColumn_ = NULL;
5533   free(rowlower_);
5534   free(rowupper_);
5535   free(collower_);
5536   free(colupper_);
5537   free(objective_);
5538   free(integerType_);
5539   free(fileName_);
5540   rowlower_ = NULL;
5541   rowupper_ = NULL;
5542   collower_ = NULL;
5543   colupper_ = NULL;
5544   objective_ = NULL;
5545   integerType_ = NULL;
5546   fileName_ = NULL;
5547   free(problemName_);
5548   free(objectiveName_);
5549   free(rhsName_);
5550   free(rangeName_);
5551   free(boundName_);
5552   problemName_ = NULL;
5553   objectiveName_ = NULL;
5554   rhsName_ = NULL;
5555   rangeName_ = NULL;
5556   boundName_ = NULL;
5557   for (int i = 0; i < numberStringElements_; i++)
5558     free(stringElements_[i]);
5559   delete[] stringElements_;
5560 }
5561 
5562 /* Release all information which can be re-calculated e.g. rowsense
5563     also any row copies OR hash tables for names */
releaseRedundantInformation()5564 void CoinMpsIO::releaseRedundantInformation()
5565 {
5566   free(rowsense_);
5567   free(rhs_);
5568   free(rowrange_);
5569   rowsense_ = NULL;
5570   rhs_ = NULL;
5571   rowrange_ = NULL;
5572   delete[] hash_[0];
5573   delete[] hash_[1];
5574   hash_[0] = 0;
5575   hash_[1] = 0;
5576   delete matrixByRow_;
5577   matrixByRow_ = NULL;
5578 }
5579 // Pass in Message handler (not deleted at end)
passInMessageHandler(CoinMessageHandler * handler)5580 void CoinMpsIO::passInMessageHandler(CoinMessageHandler *handler)
5581 {
5582   if (defaultHandler_)
5583     delete handler_;
5584   defaultHandler_ = false;
5585   handler_ = handler;
5586 }
5587 // Set language
newLanguage(CoinMessages::Language language)5588 void CoinMpsIO::newLanguage(CoinMessages::Language language)
5589 {
5590   messages_ = CoinMessage(language);
5591 }
5592 
5593 /* Read in a quadratic objective from the given filename.
5594    If filename is NULL then continues reading from previous file.  If
5595    not then the previous file is closed.
5596 
5597    No assumption is made on symmetry, positive definite etc.
5598    No check is made for duplicates or non-triangular
5599 
5600    Returns number of errors
5601 */
readQuadraticMps(const char * filename,CoinBigIndex * & columnStart,int * & column2,double * & elements,int checkSymmetry)5602 int CoinMpsIO::readQuadraticMps(const char *filename,
5603   CoinBigIndex *&columnStart, int *&column2, double *&elements,
5604   int checkSymmetry)
5605 {
5606   // Deal with filename - +1 if new, 0 if same as before, -1 if error
5607   CoinFileInput *input = 0;
5608   int returnCode = dealWithFileName(filename, "", input);
5609   if (returnCode < 0) {
5610     return -1;
5611   } else if (returnCode > 0) {
5612     delete cardReader_;
5613     cardReader_ = new CoinMpsCardReader(input, this);
5614   }
5615   // See if QUADOBJ just found
5616   if (!filename && cardReader_->whichSection() == COIN_QUAD_SECTION) {
5617     cardReader_->setWhichSection(COIN_QUAD_SECTION);
5618   } else if (cardReader_->whichSection() == COIN_CONIC_SECTION) {
5619     return -3;
5620   } else {
5621     cardReader_->readToNextSection();
5622 
5623     // Skip NAME
5624     if (cardReader_->whichSection() == COIN_NAME_SECTION)
5625       cardReader_->readToNextSection();
5626     if (cardReader_->whichSection() == COIN_QUAD_SECTION) {
5627       // save name of section
5628       free(problemName_);
5629       problemName_ = CoinStrdup(cardReader_->columnName());
5630     } else if (cardReader_->whichSection() == COIN_EOF_SECTION) {
5631       handler_->message(COIN_MPS_EOF, messages_) << fileName_
5632                                                  << CoinMessageEol;
5633       return -3;
5634     } else {
5635       handler_->message(COIN_MPS_BADFILE1, messages_) << cardReader_->card()
5636                                                       << cardReader_->cardNumber()
5637                                                       << fileName_
5638                                                       << CoinMessageEol;
5639       return -2;
5640     }
5641   }
5642 
5643   int numberErrors = 0;
5644 
5645   // Guess at size of data
5646   int maximumNonZeros = 5 * numberColumns_;
5647   // Use malloc so can use realloc
5648   int *column = reinterpret_cast< int * >(malloc(maximumNonZeros * sizeof(int)));
5649   int *column2Temp = reinterpret_cast< int * >(malloc(maximumNonZeros * sizeof(int)));
5650   double *elementTemp = reinterpret_cast< double * >(malloc(maximumNonZeros * sizeof(double)));
5651 
5652   startHash(1);
5653   int numberElements = 0;
5654 
5655   while (cardReader_->nextField() == COIN_QUAD_SECTION) {
5656     switch (cardReader_->mpsType()) {
5657     case COIN_BLANK_COLUMN:
5658       if (fabs(cardReader_->value()) > smallElement_) {
5659         if (numberElements == maximumNonZeros) {
5660           maximumNonZeros = (3 * maximumNonZeros) / 2 + 1000;
5661           column = reinterpret_cast< COINColumnIndex * >(realloc(column, maximumNonZeros * sizeof(COINColumnIndex)));
5662           column2Temp = reinterpret_cast< COINColumnIndex * >(realloc(column2Temp, maximumNonZeros * sizeof(COINColumnIndex)));
5663           elementTemp = reinterpret_cast< double * >(realloc(elementTemp, maximumNonZeros * sizeof(double)));
5664         }
5665         // get indices
5666         COINColumnIndex iColumn1 = findHash(cardReader_->columnName(), 1);
5667         COINColumnIndex iColumn2 = findHash(cardReader_->rowName(), 1);
5668 
5669         if (iColumn1 >= 0) {
5670           if (iColumn2 >= 0) {
5671             double value = cardReader_->value();
5672             column[numberElements] = iColumn1;
5673             column2Temp[numberElements] = iColumn2;
5674             elementTemp[numberElements++] = value;
5675           } else {
5676             numberErrors++;
5677             if (numberErrors < 100) {
5678               handler_->message(COIN_MPS_NOMATCHROW, messages_)
5679                 << cardReader_->rowName() << cardReader_->cardNumber() << cardReader_->card()
5680                 << CoinMessageEol;
5681             } else if (numberErrors > 100000) {
5682               handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
5683               return numberErrors;
5684             }
5685           }
5686         } else {
5687           numberErrors++;
5688           if (numberErrors < 100) {
5689             handler_->message(COIN_MPS_NOMATCHCOL, messages_)
5690               << cardReader_->columnName() << cardReader_->cardNumber() << cardReader_->card()
5691               << CoinMessageEol;
5692           } else if (numberErrors > 100000) {
5693             handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
5694             return numberErrors;
5695           }
5696         }
5697       }
5698       break;
5699     default:
5700       numberErrors++;
5701       if (numberErrors < 100) {
5702         handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
5703                                                         << cardReader_->card()
5704                                                         << CoinMessageEol;
5705       } else if (numberErrors > 100000) {
5706         handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
5707         return numberErrors;
5708       }
5709     }
5710   }
5711   if (cardReader_->whichSection() != COIN_ENDATA_SECTION && cardReader_->whichSection() != COIN_CONIC_SECTION) {
5712     handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
5713                                                     << cardReader_->card()
5714                                                     << CoinMessageEol;
5715     handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
5716     return numberErrors + 100000;
5717   }
5718 
5719   stopHash(1);
5720   // Do arrays as new [] and make column ordered
5721   columnStart = new CoinBigIndex[numberColumns_ + 1];
5722   // for counts
5723   CoinBigIndex *count = new CoinBigIndex[numberColumns_];
5724   memset(count, 0, numberColumns_ * sizeof(CoinBigIndex));
5725   CoinBigIndex i;
5726   // See about lower triangular
5727   if (checkSymmetry && numberErrors)
5728     checkSymmetry = 2; // force corrections
5729   if (checkSymmetry) {
5730     if (checkSymmetry == 1) {
5731       // just check lower triangular
5732       for (i = 0; i < numberElements; i++) {
5733         int iColumn = column[i];
5734         int iColumn2 = column2Temp[i];
5735         if (iColumn2 < iColumn) {
5736           numberErrors = -4;
5737           column[i] = iColumn2;
5738           column2Temp[i] = iColumn;
5739         }
5740       }
5741     } else {
5742       // make lower triangular
5743       for (i = 0; i < numberElements; i++) {
5744         int iColumn = column[i];
5745         int iColumn2 = column2Temp[i];
5746         if (iColumn2 < iColumn) {
5747           column[i] = iColumn2;
5748           column2Temp[i] = iColumn;
5749         }
5750       }
5751     }
5752   }
5753   for (i = 0; i < numberElements; i++) {
5754     int iColumn = column[i];
5755     count[iColumn]++;
5756   }
5757   // Do starts
5758   CoinBigIndex number = 0;
5759   columnStart[0] = 0;
5760   for (i = 0; i < numberColumns_; i++) {
5761     number += count[i];
5762     count[i] = columnStart[i];
5763     columnStart[i + 1] = number;
5764   }
5765   column2 = new int[numberElements];
5766   elements = new double[numberElements];
5767 
5768   // Get column ordering
5769   for (i = 0; i < numberElements; i++) {
5770     int iColumn = column[i];
5771     int iColumn2 = column2Temp[i];
5772     CoinBigIndex put = count[iColumn];
5773     elements[put] = elementTemp[i];
5774     column2[put++] = iColumn2;
5775     count[iColumn] = put;
5776   }
5777   free(column);
5778   free(column2Temp);
5779   free(elementTemp);
5780 
5781   // Now in column order - deal with duplicates
5782   for (i = 0; i < numberColumns_; i++)
5783     count[i] = -1;
5784 
5785   CoinBigIndex start = 0;
5786   number = 0;
5787   for (i = 0; i < numberColumns_; i++) {
5788     CoinBigIndex j;
5789     for (j = start; j < columnStart[i + 1]; j++) {
5790       int iColumn2 = column2[j];
5791       if (count[iColumn2] < 0) {
5792         count[iColumn2] = j;
5793       } else {
5794         // duplicate
5795         CoinBigIndex iOther = count[iColumn2];
5796         double value = elements[iOther] + elements[j];
5797         elements[iOther] = value;
5798         elements[j] = 0.0;
5799       }
5800     }
5801     for (j = start; j < columnStart[i + 1]; j++) {
5802       int iColumn2 = column2[j];
5803       count[iColumn2] = -1;
5804       double value = elements[j];
5805       if (value) {
5806         column2[number] = iColumn2;
5807         elements[number++] = value;
5808       }
5809     }
5810     start = columnStart[i + 1];
5811     columnStart[i + 1] = number;
5812   }
5813 
5814   delete[] count;
5815   return numberErrors;
5816 }
5817 /* Read in a list of cones from the given filename.
5818    If filename is NULL (or same) then continues reading from previous file.
5819    If not then the previous file is closed.  Code should be added to
5820    general MPS reader to read this if CSECTION
5821 
5822    No checking is done that in unique cone
5823 
5824    Arrays should be deleted by delete []
5825 
5826    Returns number of errors, -1 bad file, -2 no conic section, -3 empty section
5827 
5828    columnStart is numberCones+1 long, other number of columns in matrix
5829 
5830    coneType is 1 for QUAD, 2 for RQUAD (numberCones long)
5831 */
readConicMps(const char * filename,int * & columnStart,int * & column,int * & coneType,int & numberCones)5832 int CoinMpsIO::readConicMps(const char *filename,
5833   int *&columnStart, int *&column, int *&coneType, int &numberCones)
5834 {
5835   // Deal with filename - +1 if new, 0 if same as before, -1 if error
5836   CoinFileInput *input = 0;
5837   int returnCode = dealWithFileName(filename, "", input);
5838   if (returnCode < 0) {
5839     return -1;
5840   } else if (returnCode > 0) {
5841     delete cardReader_;
5842     cardReader_ = new CoinMpsCardReader(input, this);
5843   }
5844 
5845   // See if CSECTION just found
5846   if (!filename && cardReader_->whichSection() == COIN_CONIC_SECTION) {
5847     cardReader_->setWhichSection(COIN_CONIC_SECTION);
5848   } else {
5849     cardReader_->readToNextSection();
5850 
5851     // Skip NAME
5852     if (cardReader_->whichSection() == COIN_NAME_SECTION)
5853       cardReader_->readToNextSection();
5854     if (cardReader_->whichSection() == COIN_CONIC_SECTION) {
5855       // looks good
5856     } else if (cardReader_->whichSection() == COIN_EOF_SECTION) {
5857       handler_->message(COIN_MPS_EOF, messages_) << fileName_
5858                                                  << CoinMessageEol;
5859       return -3;
5860     } else {
5861       handler_->message(COIN_MPS_BADFILE1, messages_) << cardReader_->card()
5862                                                       << cardReader_->cardNumber()
5863                                                       << fileName_
5864                                                       << CoinMessageEol;
5865       return -2;
5866     }
5867   }
5868 
5869   numberCones = 0;
5870 
5871   // Get arrays (some too big, but ...)
5872   columnStart = new int[numberColumns_ + 1];
5873   column = new int[numberColumns_];
5874   coneType = new int[numberColumns_];
5875   // check QUAD or RQUAD (by hand) - card has had end stripped
5876   const char *quad = cardReader_->card() + strlen(cardReader_->card()) - 4;
5877   // Should be QUAD but if not don't complain
5878   int type = 1;
5879   if (!strcmp(quad, "QUAD")) {
5880     if (*(quad - 1) == 'R')
5881       type = 2;
5882   }
5883   coneType[0] = type;
5884   int numberErrors = 0;
5885   columnStart[0] = 0;
5886   int numberElements = 0;
5887   startHash(1);
5888 
5889   while (cardReader_->nextField() == COIN_CONIC_SECTION) {
5890     const char *card = cardReader_->card();
5891     if (!strncmp(card, "CSECTION", 8)) {
5892       // check QUAD or RQUAD (by hand) - card has had end stripped
5893       const char *quad = card + strlen(card) - 4;
5894       // Should be QUAD but if not don't complain
5895       int type = 1;
5896       if (!strcmp(quad, "QUAD")) {
5897         if (*(quad - 1) == 'R')
5898           type = 2;
5899       }
5900       if (numberElements == columnStart[numberCones]) {
5901         printf("Cone must have at least one column\n");
5902         abort();
5903       }
5904       columnStart[++numberCones] = numberElements;
5905       coneType[numberCones] = type;
5906       continue;
5907     }
5908     COINColumnIndex iColumn1;
5909     switch (cardReader_->mpsType()) {
5910     case COIN_BLANK_COLUMN:
5911       // get index
5912       iColumn1 = findHash(cardReader_->columnName(), 1);
5913 
5914       if (iColumn1 >= 0) {
5915         column[numberElements++] = iColumn1;
5916       } else {
5917         numberErrors++;
5918         if (numberErrors < 100) {
5919           handler_->message(COIN_MPS_NOMATCHCOL, messages_)
5920             << cardReader_->columnName() << cardReader_->cardNumber() << cardReader_->card()
5921             << CoinMessageEol;
5922         } else if (numberErrors > 100000) {
5923           handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
5924           return numberErrors;
5925         }
5926       }
5927       break;
5928     default:
5929       numberErrors++;
5930       if (numberErrors < 100) {
5931         handler_->message(COIN_MPS_BADIMAGE, messages_) << cardReader_->cardNumber()
5932                                                         << cardReader_->card()
5933                                                         << CoinMessageEol;
5934       } else if (numberErrors > 100000) {
5935         handler_->message(COIN_MPS_RETURNING, messages_) << CoinMessageEol;
5936         return numberErrors;
5937       }
5938     }
5939   }
5940   if (cardReader_->whichSection() == COIN_ENDATA_SECTION) {
5941     // Error if no cones
5942     if (!numberElements) {
5943       handler_->message(COIN_MPS_EOF, messages_) << fileName_
5944                                                  << CoinMessageEol;
5945       delete[] columnStart;
5946       delete[] column;
5947       delete[] coneType;
5948       columnStart = NULL;
5949       column = NULL;
5950       coneType = NULL;
5951       return -3;
5952     } else {
5953       columnStart[++numberCones] = numberElements;
5954     }
5955   } else {
5956     handler_->message(COIN_MPS_BADFILE1, messages_) << cardReader_->card()
5957                                                     << cardReader_->cardNumber()
5958                                                     << fileName_
5959                                                     << CoinMessageEol;
5960     delete[] columnStart;
5961     delete[] column;
5962     delete[] coneType;
5963     columnStart = NULL;
5964     column = NULL;
5965     coneType = NULL;
5966     return -2;
5967   }
5968 
5969   stopHash(1);
5970   return numberErrors;
5971 }
5972 // Add string to list
addString(int iRow,int iColumn,const char * value)5973 void CoinMpsIO::addString(int iRow, int iColumn, const char *value)
5974 {
5975   char id[20];
5976   sprintf(id, "%d,%d,", iRow, iColumn);
5977   int n = static_cast< int >(strlen(id) + strlen(value));
5978   if (numberStringElements_ == maximumStringElements_) {
5979     maximumStringElements_ = 2 * maximumStringElements_ + 100;
5980     char **temp = new char *[maximumStringElements_];
5981     for (int i = 0; i < numberStringElements_; i++)
5982       temp[i] = stringElements_[i];
5983     delete[] stringElements_;
5984     stringElements_ = temp;
5985   }
5986   char *line = reinterpret_cast< char * >(malloc(n + 1));
5987   stringElements_[numberStringElements_++] = line;
5988   strcpy(line, id);
5989   strcat(line, value);
5990 }
5991 // Decode string
decodeString(int iString,int & iRow,int & iColumn,const char * & value) const5992 void CoinMpsIO::decodeString(int iString, int &iRow, int &iColumn, const char *&value) const
5993 {
5994   iRow = -1;
5995   iColumn = -1;
5996   value = NULL;
5997   if (iString >= 0 && iString < numberStringElements_) {
5998     value = stringElements_[iString];
5999     sscanf(value, "%d,%d,", &iRow, &iColumn);
6000     value = strchr(value, ',');
6001     assert(value);
6002     value++;
6003     value = strchr(value, ',');
6004     assert(value);
6005     value++;
6006   }
6007 }
6008 // copies in strings from a CoinModel - returns number
copyStringElements(const CoinModel * model)6009 int CoinMpsIO::copyStringElements(const CoinModel *model)
6010 {
6011 #if COIN_BIG_INDEX == 0
6012   if (!model->stringsExist())
6013     return 0; // no strings
6014   assert(!numberStringElements_);
6015   /*
6016     First columns (including objective==numberRows)
6017     then RHS(==numberColumns (+1)) (with rowLower and rowUpper marked)
6018     then bounds LO==numberRows+1, UP==numberRows+2
6019   */
6020   int numberColumns = model->numberColumns();
6021   int numberRows = model->numberRows();
6022   int iColumn;
6023   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6024     const char *expr = model->getColumnObjectiveAsString(iColumn);
6025     if (strcmp(expr, "Numeric")) {
6026       addString(numberRows, iColumn, expr);
6027     }
6028     CoinModelLink triple = model->firstInColumn(iColumn);
6029     while (triple.row() >= 0) {
6030       int iRow = triple.row();
6031       const char *expr = model->getElementAsString(iRow, iColumn);
6032       if (strcmp(expr, "Numeric")) {
6033         addString(iRow, iColumn, expr);
6034       }
6035       triple = model->next(triple);
6036     }
6037   }
6038   int iRow;
6039   for (iRow = 0; iRow < numberRows; iRow++) {
6040     // for now no ranges
6041     const char *expr1 = model->getRowLowerAsString(iRow);
6042     const char *expr2 = model->getRowUpperAsString(iRow);
6043     if (strcmp(expr1, "Numeric")) {
6044       if (rowupper_[iRow] > 1.0e20 && !strcmp(expr2, "Numeric")) {
6045         // G row
6046         addString(iRow, numberColumns, expr1);
6047         rowlower_[iRow] = STRING_VALUE;
6048       } else if (!strcmp(expr1, expr2)) {
6049         // E row
6050         addString(iRow, numberColumns, expr1);
6051         rowlower_[iRow] = STRING_VALUE;
6052         addString(iRow, numberColumns + 1, expr1);
6053         rowupper_[iRow] = STRING_VALUE;
6054       } else if (rowlower_[iRow] < -1.0e20 && !strcmp(expr1, "Numeric")) {
6055         // L row
6056         addString(iRow, numberColumns + 1, expr2);
6057         rowupper_[iRow] = STRING_VALUE;
6058       } else {
6059         // Range
6060         printf("Unaable to handle string ranges row %d %s %s\n",
6061           iRow, expr1, expr2);
6062         abort();
6063       }
6064     }
6065   }
6066   // Bounds
6067   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6068     const char *expr = model->getColumnLowerAsString(iColumn);
6069     if (strcmp(expr, "Numeric")) {
6070       addString(numberRows + 1, iColumn, expr);
6071       collower_[iColumn] = STRING_VALUE;
6072     }
6073     expr = model->getColumnUpperAsString(iColumn);
6074     if (strcmp(expr, "Numeric")) {
6075       addString(numberRows + 2, iColumn, expr);
6076       colupper_[iColumn] = STRING_VALUE;
6077     }
6078   }
6079   return numberStringElements_;
6080 #else
6081   abort();
6082   return 0;
6083 #endif
6084 }
6085 // Constructor
CoinSet(int numberEntries,const int * which)6086 CoinSet::CoinSet(int numberEntries, const int *which)
6087 {
6088   numberEntries_ = numberEntries;
6089   which_ = new int[numberEntries_];
6090   weights_ = NULL;
6091   memcpy(which_, which, numberEntries_ * sizeof(int));
6092   setType_ = 1;
6093 }
6094 // Default constructor
CoinSet()6095 CoinSet::CoinSet()
6096 {
6097   numberEntries_ = 0;
6098   which_ = NULL;
6099   weights_ = NULL;
6100   setType_ = 1;
6101 }
6102 
6103 // Copy constructor
CoinSet(const CoinSet & rhs)6104 CoinSet::CoinSet(const CoinSet &rhs)
6105 {
6106   numberEntries_ = rhs.numberEntries_;
6107   setType_ = rhs.setType_;
6108   which_ = CoinCopyOfArray(rhs.which_, numberEntries_);
6109   weights_ = CoinCopyOfArray(rhs.weights_, numberEntries_);
6110 }
6111 
6112 //----------------------------------------------------------------
6113 // Assignment operator
6114 //-------------------------------------------------------------------
6115 CoinSet &
operator =(const CoinSet & rhs)6116 CoinSet::operator=(const CoinSet &rhs)
6117 {
6118   if (this != &rhs) {
6119     delete[] which_;
6120     delete[] weights_;
6121     numberEntries_ = rhs.numberEntries_;
6122     setType_ = rhs.setType_;
6123     which_ = CoinCopyOfArray(rhs.which_, numberEntries_);
6124     weights_ = CoinCopyOfArray(rhs.weights_, numberEntries_);
6125   }
6126   return *this;
6127 }
6128 
6129 // Destructor
~CoinSet()6130 CoinSet::~CoinSet()
6131 {
6132   delete[] which_;
6133   delete[] weights_;
6134 }
6135 // Constructor
CoinSosSet(int numberEntries,const int * which,const double * weights,int type)6136 CoinSosSet::CoinSosSet(int numberEntries, const int *which, const double *weights, int type)
6137   : CoinSet(numberEntries, which)
6138 {
6139   weights_ = new double[numberEntries_];
6140   memcpy(weights_, weights, numberEntries_ * sizeof(double));
6141   setType_ = type;
6142   double last = weights_[0];
6143   int i;
6144   bool allSame = true;
6145   for (i = 1; i < numberEntries_; i++) {
6146     if (weights_[i] != last) {
6147       allSame = false;
6148       break;
6149     }
6150   }
6151   if (allSame) {
6152     for (i = 0; i < numberEntries_; i++)
6153       weights_[i] = i;
6154   }
6155 }
6156 
6157 // Destructor
~CoinSosSet()6158 CoinSosSet::~CoinSosSet()
6159 {
6160 }
6161 #ifdef USE_SBB
6162 #include "SbbModel.hpp"
6163 #include "SbbBranchActual.hpp"
6164 // returns an object of type SbbObject
6165 SbbObject *
sbbObject(SbbModel * model) const6166 CoinSosSet::sbbObject(SbbModel *model) const
6167 {
6168   // which are matrix here - need to put as integer index
6169   abort();
6170   return new SbbSOS(model, numberEntries_, which_, weights_, 0, setType_);
6171 }
6172 #endif
6173 
6174 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
6175 */
6176