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