1 | /* $Id: CoinMpsIO.hpp 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 | #ifndef CoinMpsIO_H |
7 | #define CoinMpsIO_H |
8 | |
9 | #if defined(_MSC_VER) |
10 | // Turn off compiler warning about long names |
11 | # pragma warning(disable:4786) |
12 | #endif |
13 | |
14 | #include <vector> |
15 | #include <string> |
16 | |
17 | #include "CoinUtilsConfig.h" |
18 | #include "CoinPackedMatrix.hpp" |
19 | #include "CoinMessageHandler.hpp" |
20 | #include "CoinFileIO.hpp" |
21 | class CoinModel; |
22 | |
23 | /// The following lengths are in decreasing order (for 64 bit etc) |
24 | /// Large enough to contain element index |
25 | /// This is already defined as CoinBigIndex |
26 | /// Large enough to contain column index |
27 | typedef int COINColumnIndex; |
28 | |
29 | /// Large enough to contain row index (or basis) |
30 | typedef int COINRowIndex; |
31 | |
32 | // We are allowing free format - but there is a limit! |
33 | // User can override by using CXXFLAGS += -DCOIN_MAX_FIELD_LENGTH=nnn |
34 | #ifndef COIN_MAX_FIELD_LENGTH |
35 | #define COIN_MAX_FIELD_LENGTH 160 |
36 | #endif |
37 | #define MAX_CARD_LENGTH 5*COIN_MAX_FIELD_LENGTH+80 |
38 | |
39 | enum COINSectionType { COIN_NO_SECTION, COIN_NAME_SECTION, COIN_ROW_SECTION, |
40 | COIN_COLUMN_SECTION, |
41 | COIN_RHS_SECTION, COIN_RANGES_SECTION, COIN_BOUNDS_SECTION, |
42 | COIN_ENDATA_SECTION, COIN_EOF_SECTION, COIN_QUADRATIC_SECTION, |
43 | COIN_CONIC_SECTION,COIN_QUAD_SECTION,COIN_SOS_SECTION, |
44 | COIN_BASIS_SECTION,COIN_UNKNOWN_SECTION |
45 | }; |
46 | |
47 | enum COINMpsType { COIN_N_ROW, COIN_E_ROW, COIN_L_ROW, COIN_G_ROW, |
48 | COIN_BLANK_COLUMN, COIN_S1_COLUMN, COIN_S2_COLUMN, COIN_S3_COLUMN, |
49 | COIN_INTORG, COIN_INTEND, COIN_SOSEND, COIN_UNSET_BOUND, |
50 | COIN_UP_BOUND, COIN_FX_BOUND, COIN_LO_BOUND, COIN_FR_BOUND, |
51 | COIN_MI_BOUND, COIN_PL_BOUND, COIN_BV_BOUND, COIN_UI_BOUND, COIN_LI_BOUND, |
52 | COIN_SC_BOUND, COIN_S1_BOUND, COIN_S2_BOUND, |
53 | COIN_BS_BASIS, COIN_XL_BASIS, COIN_XU_BASIS, |
54 | COIN_LL_BASIS, COIN_UL_BASIS, COIN_UNKNOWN_MPS_TYPE |
55 | }; |
56 | class CoinMpsIO; |
57 | /// Very simple code for reading MPS data |
58 | class CoinMpsCardReader { |
59 | |
60 | public: |
61 | |
62 | /**@name Constructor and destructor */ |
63 | //@{ |
64 | /// Constructor expects file to be open |
65 | /// This one takes gzFile if fp null |
66 | CoinMpsCardReader ( CoinFileInput *input, CoinMpsIO * reader ); |
67 | |
68 | /// Destructor |
69 | ~CoinMpsCardReader ( ); |
70 | //@} |
71 | |
72 | |
73 | /**@name card stuff */ |
74 | //@{ |
75 | /// Read to next section |
76 | COINSectionType readToNextSection ( ); |
77 | /// Gets next field and returns section type e.g. COIN_COLUMN_SECTION |
78 | COINSectionType nextField ( ); |
79 | /** Gets next field for .gms file and returns type. |
80 | -1 - EOF |
81 | 0 - what we expected (and processed so pointer moves past) |
82 | 1 - not what we expected |
83 | leading blanks always ignored |
84 | input types |
85 | 0 - anything - stops on non blank card |
86 | 1 - name (in columnname) |
87 | 2 - value |
88 | 3 - value name pair |
89 | 4 - equation type |
90 | 5 - ; |
91 | */ |
92 | int nextGmsField ( int expectedType ); |
93 | /// Returns current section type |
94 | inline COINSectionType whichSection ( ) const { |
95 | return section_; |
96 | } |
97 | /// Sets current section type |
98 | inline void setWhichSection(COINSectionType section ) { |
99 | section_=section; |
100 | } |
101 | /// Sees if free format. |
102 | inline bool freeFormat() const |
103 | { return freeFormat_;} |
104 | /// Sets whether free format. Mainly for blank RHS etc |
105 | inline void setFreeFormat(bool yesNo) |
106 | { freeFormat_=yesNo;} |
107 | /// Only for first field on card otherwise BLANK_COLUMN |
108 | /// e.g. COIN_E_ROW |
109 | inline COINMpsType mpsType ( ) const { |
110 | return mpsType_; |
111 | } |
112 | /// Reads and cleans card - taking out trailing blanks - return 1 if EOF |
113 | int cleanCard(); |
114 | /// Returns row name of current field |
115 | inline const char *rowName ( ) const { |
116 | return rowName_; |
117 | } |
118 | /// Returns column name of current field |
119 | inline const char *columnName ( ) const { |
120 | return columnName_; |
121 | } |
122 | /// Returns value in current field |
123 | inline double value ( ) const { |
124 | return value_; |
125 | } |
126 | /// Returns value as string in current field |
127 | inline const char *valueString ( ) const { |
128 | return valueString_; |
129 | } |
130 | /// Whole card (for printing) |
131 | inline const char *card ( ) const { |
132 | return card_; |
133 | } |
134 | /// Whole card - so we look at it (not const so nextBlankOr will work for gms reader) |
135 | inline char *mutableCard ( ) { |
136 | return card_; |
137 | } |
138 | /// set position (again so gms reader will work) |
139 | inline void setPosition(char * position) |
140 | { position_=position;} |
141 | /// get position (again so gms reader will work) |
142 | inline char * getPosition() const |
143 | { return position_;} |
144 | /// Returns card number |
145 | inline CoinBigIndex cardNumber ( ) const { |
146 | return cardNumber_; |
147 | } |
148 | /// Returns file input |
149 | inline CoinFileInput * fileInput ( ) const { |
150 | return input_; |
151 | } |
152 | /// Sets whether strings allowed |
153 | inline void setStringsAllowed() |
154 | { stringsAllowed_=true;} |
155 | //@} |
156 | |
157 | ////////////////// data ////////////////// |
158 | protected: |
159 | |
160 | /**@name data */ |
161 | //@{ |
162 | /// Current value |
163 | double value_; |
164 | /// Current card image |
165 | char card_[MAX_CARD_LENGTH]; |
166 | /// Current position within card image |
167 | char *position_; |
168 | /// End of card |
169 | char *eol_; |
170 | /// Current COINMpsType |
171 | COINMpsType mpsType_; |
172 | /// Current row name |
173 | char rowName_[COIN_MAX_FIELD_LENGTH]; |
174 | /// Current column name |
175 | char columnName_[COIN_MAX_FIELD_LENGTH]; |
176 | /// File input |
177 | CoinFileInput *input_; |
178 | /// Which section we think we are in |
179 | COINSectionType section_; |
180 | /// Card number |
181 | CoinBigIndex cardNumber_; |
182 | /// Whether free format. Just for blank RHS etc |
183 | bool freeFormat_; |
184 | /// Whether IEEE - 0 no, 1 INTEL, 2 not INTEL |
185 | int ieeeFormat_; |
186 | /// If all names <= 8 characters then allow embedded blanks |
187 | bool eightChar_; |
188 | /// MpsIO |
189 | CoinMpsIO * reader_; |
190 | /// Message handler |
191 | CoinMessageHandler * handler_; |
192 | /// Messages |
193 | CoinMessages messages_; |
194 | /// Current element as characters (only if strings allowed) |
195 | char valueString_[COIN_MAX_FIELD_LENGTH]; |
196 | /// Whether strings allowed |
197 | bool stringsAllowed_; |
198 | //@} |
199 | public: |
200 | /**@name methods */ |
201 | //@{ |
202 | /// type - 0 normal, 1 INTEL IEEE, 2 other IEEE |
203 | double osi_strtod(char * ptr, char ** output, int type); |
204 | /// remove blanks |
205 | static void strcpyAndCompress ( char *to, const char *from ); |
206 | /// |
207 | static char * nextBlankOr ( char *image ); |
208 | /// For strings |
209 | double osi_strtod(char * ptr, char ** output); |
210 | //@} |
211 | |
212 | }; |
213 | |
214 | //############################################################################# |
215 | #ifdef USE_SBB |
216 | class SbbObject; |
217 | class SbbModel; |
218 | #endif |
219 | /// Very simple class for containing data on set |
220 | class CoinSet { |
221 | |
222 | public: |
223 | |
224 | /**@name Constructor and destructor */ |
225 | //@{ |
226 | /// Default constructor |
227 | CoinSet ( ); |
228 | /// Constructor |
229 | CoinSet ( int numberEntries, const int * which); |
230 | |
231 | /// Copy constructor |
232 | CoinSet (const CoinSet &); |
233 | |
234 | /// Assignment operator |
235 | CoinSet & operator=(const CoinSet& rhs); |
236 | |
237 | /// Destructor |
238 | virtual ~CoinSet ( ); |
239 | //@} |
240 | |
241 | |
242 | /**@name gets */ |
243 | //@{ |
244 | /// Returns number of entries |
245 | inline int numberEntries ( ) const |
246 | { return numberEntries_; } |
247 | /// Returns type of set - 1 =SOS1, 2 =SOS2 |
248 | inline int setType ( ) const |
249 | { return setType_; } |
250 | /// Returns list of variables |
251 | inline const int * which ( ) const |
252 | { return which_; } |
253 | /// Returns weights |
254 | inline const double * weights ( ) const |
255 | { return weights_; } |
256 | //@} |
257 | |
258 | #ifdef USE_SBB |
259 | /**@name Use in sbb */ |
260 | //@{ |
261 | /// returns an object of type SbbObject |
262 | virtual SbbObject * sbbObject(SbbModel * model) const |
263 | { return NULL;} |
264 | //@} |
265 | #endif |
266 | |
267 | ////////////////// data ////////////////// |
268 | protected: |
269 | |
270 | /**@name data */ |
271 | //@{ |
272 | /// Number of entries |
273 | int numberEntries_; |
274 | /// type of set |
275 | int setType_; |
276 | /// Which variables are in set |
277 | int * which_; |
278 | /// Weights |
279 | double * weights_; |
280 | //@} |
281 | }; |
282 | |
283 | //############################################################################# |
284 | /// Very simple class for containing SOS set |
285 | class CoinSosSet : public CoinSet{ |
286 | |
287 | public: |
288 | |
289 | /**@name Constructor and destructor */ |
290 | //@{ |
291 | /// Constructor |
292 | CoinSosSet ( int numberEntries, const int * which, const double * weights, int type); |
293 | |
294 | /// Destructor |
295 | virtual ~CoinSosSet ( ); |
296 | //@} |
297 | |
298 | |
299 | #ifdef USE_SBB |
300 | /**@name Use in sbb */ |
301 | //@{ |
302 | /// returns an object of type SbbObject |
303 | virtual SbbObject * sbbObject(SbbModel * model) const ; |
304 | //@} |
305 | #endif |
306 | |
307 | ////////////////// data ////////////////// |
308 | protected: |
309 | |
310 | /**@name data */ |
311 | //@{ |
312 | //@} |
313 | }; |
314 | |
315 | //############################################################################# |
316 | |
317 | /** MPS IO Interface |
318 | |
319 | This class can be used to read in mps files without a solver. After |
320 | reading the file, the CoinMpsIO object contains all relevant data, which |
321 | may be more than a particular OsiSolverInterface allows for. Items may |
322 | be deleted to allow for flexibility of data storage. |
323 | |
324 | The implementation makes the CoinMpsIO object look very like a dummy solver, |
325 | as the same conventions are used. |
326 | */ |
327 | |
328 | class CoinMpsIO { |
329 | friend void CoinMpsIOUnitTest(const std::string & mpsDir); |
330 | |
331 | public: |
332 | |
333 | /** @name Methods to retrieve problem information |
334 | |
335 | These methods return information about the problem held by the CoinMpsIO |
336 | object. |
337 | |
338 | Querying an object that has no data associated with it result in zeros for |
339 | the number of rows and columns, and NULL pointers from the methods that |
340 | return vectors. Const pointers returned from any data-query method are |
341 | always valid |
342 | */ |
343 | //@{ |
344 | /// Get number of columns |
345 | int getNumCols() const; |
346 | |
347 | /// Get number of rows |
348 | int getNumRows() const; |
349 | |
350 | /// Get number of nonzero elements |
351 | int getNumElements() const; |
352 | |
353 | /// Get pointer to array[getNumCols()] of column lower bounds |
354 | const double * getColLower() const; |
355 | |
356 | /// Get pointer to array[getNumCols()] of column upper bounds |
357 | const double * getColUpper() const; |
358 | |
359 | /** Get pointer to array[getNumRows()] of constraint senses. |
360 | <ul> |
361 | <li>'L': <= constraint |
362 | <li>'E': = constraint |
363 | <li>'G': >= constraint |
364 | <li>'R': ranged constraint |
365 | <li>'N': free constraint |
366 | </ul> |
367 | */ |
368 | const char * getRowSense() const; |
369 | |
370 | /** Get pointer to array[getNumRows()] of constraint right-hand sides. |
371 | |
372 | Given constraints with upper (rowupper) and/or lower (rowlower) bounds, |
373 | the constraint right-hand side (rhs) is set as |
374 | <ul> |
375 | <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] |
376 | <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] |
377 | <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] |
378 | <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0 |
379 | </ul> |
380 | */ |
381 | const double * getRightHandSide() const; |
382 | |
383 | /** Get pointer to array[getNumRows()] of row ranges. |
384 | |
385 | Given constraints with upper (rowupper) and/or lower (rowlower) bounds, |
386 | the constraint range (rowrange) is set as |
387 | <ul> |
388 | <li> if rowsense()[i] == 'R' then |
389 | rowrange()[i] == rowupper()[i] - rowlower()[i] |
390 | <li> if rowsense()[i] != 'R' then |
391 | rowrange()[i] is 0.0 |
392 | </ul> |
393 | Put another way, only range constraints have a nontrivial value for |
394 | rowrange. |
395 | */ |
396 | const double * getRowRange() const; |
397 | |
398 | /// Get pointer to array[getNumRows()] of row lower bounds |
399 | const double * getRowLower() const; |
400 | |
401 | /// Get pointer to array[getNumRows()] of row upper bounds |
402 | const double * getRowUpper() const; |
403 | |
404 | /// Get pointer to array[getNumCols()] of objective function coefficients |
405 | const double * getObjCoefficients() const; |
406 | |
407 | /// Get pointer to row-wise copy of the coefficient matrix |
408 | const CoinPackedMatrix * getMatrixByRow() const; |
409 | |
410 | /// Get pointer to column-wise copy of the coefficient matrix |
411 | const CoinPackedMatrix * getMatrixByCol() const; |
412 | |
413 | /// Return true if column is a continuous variable |
414 | bool isContinuous(int colNumber) const; |
415 | |
416 | /** Return true if a column is an integer variable |
417 | |
418 | Note: This function returns true if the the column |
419 | is a binary or general integer variable. |
420 | */ |
421 | bool isInteger(int columnNumber) const; |
422 | |
423 | /** Returns array[getNumCols()] specifying if a variable is integer. |
424 | |
425 | At present, simply coded as zero (continuous) and non-zero (integer) |
426 | May be extended at a later date. |
427 | */ |
428 | const char * integerColumns() const; |
429 | |
430 | /** Returns the row name for the specified index. |
431 | |
432 | Returns 0 if the index is out of range. |
433 | */ |
434 | const char * rowName(int index) const; |
435 | |
436 | /** Returns the column name for the specified index. |
437 | |
438 | Returns 0 if the index is out of range. |
439 | */ |
440 | const char * columnName(int index) const; |
441 | |
442 | /** Returns the index for the specified row name |
443 | |
444 | Returns -1 if the name is not found. |
445 | Returns numberRows for the objective row and > numberRows for |
446 | dropped free rows. |
447 | */ |
448 | int rowIndex(const char * name) const; |
449 | |
450 | /** Returns the index for the specified column name |
451 | |
452 | Returns -1 if the name is not found. |
453 | */ |
454 | int columnIndex(const char * name) const; |
455 | |
456 | /** Returns the (constant) objective offset |
457 | |
458 | This is the RHS entry for the objective row |
459 | */ |
460 | double objectiveOffset() const; |
461 | /// Set objective offset |
462 | inline void setObjectiveOffset(double value) |
463 | { objectiveOffset_=value;} |
464 | |
465 | /// Return the problem name |
466 | const char * getProblemName() const; |
467 | |
468 | /// Return the objective name |
469 | const char * getObjectiveName() const; |
470 | |
471 | /// Return the RHS vector name |
472 | const char * getRhsName() const; |
473 | |
474 | /// Return the range vector name |
475 | const char * getRangeName() const; |
476 | |
477 | /// Return the bound vector name |
478 | const char * getBoundName() const; |
479 | /// Number of string elements |
480 | inline int numberStringElements() const |
481 | { return numberStringElements_;} |
482 | /// String element |
483 | inline const char * stringElement(int i) const |
484 | { return stringElements_[i];} |
485 | //@} |
486 | |
487 | |
488 | /** @name Methods to set problem information |
489 | |
490 | Methods to load a problem into the CoinMpsIO object. |
491 | */ |
492 | //@{ |
493 | |
494 | /// Set the problem data |
495 | void setMpsData(const CoinPackedMatrix& m, const double infinity, |
496 | const double* collb, const double* colub, |
497 | const double* obj, const char* integrality, |
498 | const double* rowlb, const double* rowub, |
499 | char const * const * const colnames, |
500 | char const * const * const rownames); |
501 | void setMpsData(const CoinPackedMatrix& m, const double infinity, |
502 | const double* collb, const double* colub, |
503 | const double* obj, const char* integrality, |
504 | const double* rowlb, const double* rowub, |
505 | const std::vector<std::string> & colnames, |
506 | const std::vector<std::string> & rownames); |
507 | void setMpsData(const CoinPackedMatrix& m, const double infinity, |
508 | const double* collb, const double* colub, |
509 | const double* obj, const char* integrality, |
510 | const char* rowsen, const double* rowrhs, |
511 | const double* rowrng, |
512 | char const * const * const colnames, |
513 | char const * const * const rownames); |
514 | void setMpsData(const CoinPackedMatrix& m, const double infinity, |
515 | const double* collb, const double* colub, |
516 | const double* obj, const char* integrality, |
517 | const char* rowsen, const double* rowrhs, |
518 | const double* rowrng, |
519 | const std::vector<std::string> & colnames, |
520 | const std::vector<std::string> & rownames); |
521 | |
522 | /** Pass in an array[getNumCols()] specifying if a variable is integer. |
523 | |
524 | At present, simply coded as zero (continuous) and non-zero (integer) |
525 | May be extended at a later date. |
526 | */ |
527 | void copyInIntegerInformation(const char * integerInformation); |
528 | |
529 | /// Set problem name |
530 | void setProblemName(const char *name) ; |
531 | |
532 | /// Set objective name |
533 | void setObjectiveName(const char *name) ; |
534 | |
535 | //@} |
536 | |
537 | /** @name Parameter set/get methods |
538 | |
539 | Methods to set and retrieve MPS IO parameters. |
540 | */ |
541 | |
542 | //@{ |
543 | /// Set infinity |
544 | void setInfinity(double value); |
545 | |
546 | /// Get infinity |
547 | double getInfinity() const; |
548 | |
549 | /// Set default upper bound for integer variables |
550 | void setDefaultBound(int value); |
551 | |
552 | /// Get default upper bound for integer variables |
553 | int getDefaultBound() const; |
554 | /// Whether to allow string elements |
555 | inline int allowStringElements() const |
556 | { return allowStringElements_;} |
557 | /// Whether to allow string elements (0 no, 1 yes, 2 yes and try flip) |
558 | inline void setAllowStringElements(int yesNo) |
559 | { allowStringElements_ = yesNo;} |
560 | /** Small element value - elements less than this set to zero on input |
561 | default is 1.0e-14 */ |
562 | inline double getSmallElementValue() const |
563 | { return smallElement_;} |
564 | inline void setSmallElementValue(double value) |
565 | { smallElement_=value;} |
566 | //@} |
567 | |
568 | |
569 | /** @name Methods for problem input and output |
570 | |
571 | Methods to read and write MPS format problem files. |
572 | |
573 | The read and write methods return the number of errors that occurred during |
574 | the IO operation, or -1 if no file is opened. |
575 | |
576 | \note |
577 | If the CoinMpsIO class was compiled with support for libz then |
578 | readMps will automatically try to append .gz to the file name and open it as |
579 | a compressed file if the specified file name cannot be opened. |
580 | (Automatic append of the .bz2 suffix when libbz is used is on the TODO list.) |
581 | |
582 | \todo |
583 | Allow for file pointers and positioning |
584 | */ |
585 | |
586 | //@{ |
587 | /// Set the current file name for the CoinMpsIO object |
588 | void setFileName(const char * name); |
589 | |
590 | /// Get the current file name for the CoinMpsIO object |
591 | const char * getFileName() const; |
592 | |
593 | /** Read a problem in MPS format from the given filename. |
594 | |
595 | Use "stdin" or "-" to read from stdin. |
596 | */ |
597 | int readMps(const char *filename, const char *extension = "mps" ); |
598 | |
599 | /** Read a problem in MPS format from the given filename. |
600 | |
601 | Use "stdin" or "-" to read from stdin. |
602 | But do sets as well |
603 | */ |
604 | int readMps(const char *filename, const char *extension , |
605 | int & numberSets, CoinSet **& sets); |
606 | |
607 | /** Read a problem in MPS format from a previously opened file |
608 | |
609 | More precisely, read a problem using a CoinMpsCardReader object already |
610 | associated with this CoinMpsIO object. |
611 | |
612 | \todo |
613 | Provide an interface that will allow a client to associate a |
614 | CoinMpsCardReader object with a CoinMpsIO object by setting the |
615 | cardReader_ field. |
616 | */ |
617 | int readMps(); |
618 | /// and |
619 | int readMps(int & numberSets, CoinSet **& sets); |
620 | /** Read a basis in MPS format from the given filename. |
621 | If VALUES on NAME card and solution not NULL fills in solution |
622 | status values as for CoinWarmStartBasis (but one per char) |
623 | -1 file error, 0 normal, 1 has solution values |
624 | |
625 | Use "stdin" or "-" to read from stdin. |
626 | |
627 | If sizes of names incorrect - read without names |
628 | */ |
629 | int readBasis(const char *filename, const char *extension , |
630 | double * solution, unsigned char *rowStatus, unsigned char *columnStatus, |
631 | const std::vector<std::string> & colnames,int numberColumns, |
632 | const std::vector<std::string> & rownames, int numberRows); |
633 | |
634 | /** Read a problem in GAMS format from the given filename. |
635 | |
636 | Use "stdin" or "-" to read from stdin. |
637 | if convertObjective then massages objective column |
638 | */ |
639 | int readGms(const char *filename, const char *extension = "gms" ,bool convertObjective=false); |
640 | |
641 | /** Read a problem in GAMS format from the given filename. |
642 | |
643 | Use "stdin" or "-" to read from stdin. |
644 | But do sets as well |
645 | */ |
646 | int readGms(const char *filename, const char *extension , |
647 | int & numberSets, CoinSet **& sets); |
648 | |
649 | /** Read a problem in GAMS format from a previously opened file |
650 | |
651 | More precisely, read a problem using a CoinMpsCardReader object already |
652 | associated with this CoinMpsIO object. |
653 | |
654 | */ |
655 | // Not for now int readGms(); |
656 | /// and |
657 | int readGms(int & numberSets, CoinSet **& sets); |
658 | /** Read a problem in GMPL (subset of AMPL) format from the given filenames. |
659 | */ |
660 | int readGMPL(const char *modelName, const char * dataName=nullptr, bool keepNames=false); |
661 | |
662 | /** Write the problem in MPS format to a file with the given filename. |
663 | |
664 | \param compression can be set to three values to indicate what kind |
665 | of file should be written |
666 | <ul> |
667 | <li> 0: plain text (default) |
668 | <li> 1: gzip compressed (.gz is appended to \c filename) |
669 | <li> 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) |
670 | </ul> |
671 | If the library was not compiled with the requested compression then |
672 | writeMps falls back to writing a plain text file. |
673 | |
674 | \param formatType specifies the precision to used for values in the |
675 | MPS file |
676 | <ul> |
677 | <li> 0: normal precision (default) |
678 | <li> 1: extra accuracy |
679 | <li> 2: IEEE hex |
680 | </ul> |
681 | |
682 | \param numberAcross specifies whether 1 or 2 (default) values should be |
683 | specified on every data line in the MPS file. |
684 | |
685 | \param quadratic specifies quadratic objective to be output |
686 | */ |
687 | int writeMps(const char *filename, int compression = 0, |
688 | int formatType = 0, int numberAcross = 2, |
689 | CoinPackedMatrix * quadratic = nullptr, |
690 | int numberSOS=0,const CoinSet * setInfo=nullptr) const; |
691 | |
692 | /// Return card reader object so can see what last card was e.g. QUADOBJ |
693 | inline const CoinMpsCardReader * reader() const |
694 | { return cardReader_;} |
695 | |
696 | /** Read in a quadratic objective from the given filename. |
697 | |
698 | If filename is NULL (or the same as the currently open file) then |
699 | reading continues from the current file. |
700 | If not, the file is closed and the specified file is opened. |
701 | |
702 | Code should be added to |
703 | general MPS reader to read this if QSECTION |
704 | Data is assumed to be Q and objective is c + 1/2 xT Q x |
705 | No assumption is made for symmetry, positive definite, etc. |
706 | No check is made for duplicates or non-triangular if checkSymmetry==0. |
707 | If 1 checks lower triangular (so off diagonal should be 2*Q) |
708 | if 2 makes lower triangular and assumes full Q (but adds off diagonals) |
709 | |
710 | Arrays should be deleted by delete [] |
711 | |
712 | Returns number of errors: |
713 | <ul> |
714 | <li> -1: bad file |
715 | <li> -2: no Quadratic section |
716 | <li> -3: an empty section |
717 | <li> +n: then matching errors etc (symmetry forced) |
718 | <li> -4: no matching errors but fails triangular test |
719 | (triangularity forced) |
720 | </ul> |
721 | columnStart is numberColumns+1 long, others numberNonZeros |
722 | */ |
723 | int readQuadraticMps(const char * filename, |
724 | int * &columnStart, int * &column, double * &elements, |
725 | int checkSymmetry); |
726 | |
727 | /** Read in a list of cones from the given filename. |
728 | |
729 | If filename is NULL (or the same as the currently open file) then |
730 | reading continues from the current file. |
731 | If not, the file is closed and the specified file is opened. |
732 | |
733 | Code should be added to |
734 | general MPS reader to read this if CSECTION |
735 | No checking is done that in unique cone |
736 | |
737 | Arrays should be deleted by delete [] |
738 | |
739 | Returns number of errors, -1 bad file, -2 no conic section, |
740 | -3 empty section |
741 | |
742 | columnStart is numberCones+1 long, other number of columns in matrix |
743 | */ |
744 | int readConicMps(const char * filename, |
745 | int * &columnStart, int * &column, int & numberCones); |
746 | /// Set whether to move objective from matrix |
747 | inline void setConvertObjective(bool trueFalse) |
748 | { convertObjective_=trueFalse;} |
749 | /// copies in strings from a CoinModel - returns number |
750 | int copyStringElements(const CoinModel * model); |
751 | //@} |
752 | |
753 | /** @name Constructors and destructors */ |
754 | //@{ |
755 | /// Default Constructor |
756 | CoinMpsIO(); |
757 | |
758 | /// Copy constructor |
759 | CoinMpsIO (const CoinMpsIO &); |
760 | |
761 | /// Assignment operator |
762 | CoinMpsIO & operator=(const CoinMpsIO& rhs); |
763 | |
764 | /// Destructor |
765 | ~CoinMpsIO (); |
766 | //@} |
767 | |
768 | |
769 | /**@name Message handling */ |
770 | //@{ |
771 | /** Pass in Message handler |
772 | |
773 | Supply a custom message handler. It will not be destroyed when the |
774 | CoinMpsIO object is destroyed. |
775 | */ |
776 | void passInMessageHandler(CoinMessageHandler * handler); |
777 | |
778 | /// Set the language for messages. |
779 | void newLanguage(CoinMessages::Language language); |
780 | |
781 | /// Set the language for messages. |
782 | inline void setLanguage(CoinMessages::Language language) {newLanguage(language);} |
783 | |
784 | /// Return the message handler |
785 | inline CoinMessageHandler * messageHandler() const {return handler_;} |
786 | |
787 | /// Return the messages |
788 | inline CoinMessages messages() {return messages_;} |
789 | /// Return the messages pointer |
790 | inline CoinMessages * messagesPointer() {return & messages_;} |
791 | //@} |
792 | |
793 | |
794 | /**@name Methods to release storage |
795 | |
796 | These methods allow the client to reduce the storage used by the CoinMpsIO |
797 | object be selectively releasing unneeded problem information. |
798 | */ |
799 | //@{ |
800 | /** Release all information which can be re-calculated. |
801 | |
802 | E.g., row sense, copies of rows, hash tables for names. |
803 | */ |
804 | void releaseRedundantInformation(); |
805 | |
806 | /// Release all row information (lower, upper) |
807 | void releaseRowInformation(); |
808 | |
809 | /// Release all column information (lower, upper, objective) |
810 | void releaseColumnInformation(); |
811 | |
812 | /// Release integer information |
813 | void releaseIntegerInformation(); |
814 | |
815 | /// Release row names |
816 | void releaseRowNames(); |
817 | |
818 | /// Release column names |
819 | void releaseColumnNames(); |
820 | |
821 | /// Release matrix information |
822 | void releaseMatrixInformation(); |
823 | //@} |
824 | |
825 | protected: |
826 | |
827 | /**@name Miscellaneous helper functions */ |
828 | //@{ |
829 | |
830 | /// Utility method used several times to implement public methods |
831 | void |
832 | setMpsDataWithoutRowAndColNames( |
833 | const CoinPackedMatrix& m, const double infinity, |
834 | const double* collb, const double* colub, |
835 | const double* obj, const char* integrality, |
836 | const double* rowlb, const double* rowub); |
837 | void |
838 | setMpsDataColAndRowNames( |
839 | const std::vector<std::string> & colnames, |
840 | const std::vector<std::string> & rownames); |
841 | void |
842 | setMpsDataColAndRowNames( |
843 | char const * const * const colnames, |
844 | char const * const * const rownames); |
845 | |
846 | |
847 | /// Does the heavy lifting for destruct and assignment. |
848 | void gutsOfDestructor(); |
849 | |
850 | /// Does the heavy lifting for copy and assignment. |
851 | void gutsOfCopy(const CoinMpsIO &); |
852 | |
853 | /// Clears problem data from the CoinMpsIO object. |
854 | void freeAll(); |
855 | |
856 | |
857 | /** A quick inlined function to convert from lb/ub style constraint |
858 | definition to sense/rhs/range style */ |
859 | inline void |
860 | convertBoundToSense(const double lower, const double upper, |
861 | char& sense, double& right, double& range) const; |
862 | /** A quick inlined function to convert from sense/rhs/range stryle |
863 | constraint definition to lb/ub style */ |
864 | inline void |
865 | convertSenseToBound(const char sense, const double right, |
866 | const double range, |
867 | double& lower, double& upper) const; |
868 | |
869 | /** Deal with a filename |
870 | |
871 | As the name says. |
872 | Returns +1 if the file name is new, 0 if it's the same as before |
873 | (i.e., matches fileName_), and -1 if there's an error and the file |
874 | can't be opened. |
875 | Handles automatic append of .gz suffix when compiled with libz. |
876 | |
877 | \todo |
878 | Add automatic append of .bz2 suffix when compiled with libbz. |
879 | */ |
880 | |
881 | int dealWithFileName(const char * filename, const char * extension, |
882 | CoinFileInput * &input); |
883 | /** Add string to list |
884 | iRow==numberRows is objective, nr+1 is lo, nr+2 is up |
885 | iColumn==nc is rhs (can't cope with ranges at present) |
886 | */ |
887 | void addString(int iRow,int iColumn, const char * value); |
888 | /// Decode string |
889 | void decodeString(int iString, int & iRow, int & iColumn, const char * & value) const; |
890 | //@} |
891 | |
892 | |
893 | // for hashing |
894 | typedef struct { |
895 | int index, next; |
896 | } CoinHashLink; |
897 | |
898 | /**@name Hash table methods */ |
899 | //@{ |
900 | /// Creates hash list for names (section = 0 for rows, 1 columns) |
901 | void startHash ( char **names, const int number , int section ); |
902 | /// This one does it when names are already in |
903 | void startHash ( int section ) const; |
904 | /// Deletes hash storage |
905 | void stopHash ( int section ); |
906 | /// Finds match using hash, -1 not found |
907 | int findHash ( const char *name , int section ) const; |
908 | //@} |
909 | |
910 | /**@name Cached problem information */ |
911 | //@{ |
912 | /// Problem name |
913 | char * problemName_; |
914 | |
915 | /// Objective row name |
916 | char * objectiveName_; |
917 | |
918 | /// Right-hand side vector name |
919 | char * rhsName_; |
920 | |
921 | /// Range vector name |
922 | char * rangeName_; |
923 | |
924 | /// Bounds vector name |
925 | char * boundName_; |
926 | |
927 | /// Number of rows |
928 | int numberRows_; |
929 | |
930 | /// Number of columns |
931 | int numberColumns_; |
932 | |
933 | /// Number of coefficients |
934 | CoinBigIndex numberElements_; |
935 | |
936 | /// Pointer to dense vector of row sense indicators |
937 | mutable char *rowsense_; |
938 | |
939 | /// Pointer to dense vector of row right-hand side values |
940 | mutable double *rhs_; |
941 | |
942 | /** Pointer to dense vector of slack variable upper bounds for range |
943 | constraints (undefined for non-range rows) |
944 | */ |
945 | mutable double *rowrange_; |
946 | |
947 | /// Pointer to row-wise copy of problem matrix coefficients. |
948 | mutable CoinPackedMatrix *matrixByRow_; |
949 | |
950 | /// Pointer to column-wise copy of problem matrix coefficients. |
951 | CoinPackedMatrix *matrixByColumn_; |
952 | |
953 | /// Pointer to dense vector of row lower bounds |
954 | double * rowlower_; |
955 | |
956 | /// Pointer to dense vector of row upper bounds |
957 | double * rowupper_; |
958 | |
959 | /// Pointer to dense vector of column lower bounds |
960 | double * collower_; |
961 | |
962 | /// Pointer to dense vector of column upper bounds |
963 | double * colupper_; |
964 | |
965 | /// Pointer to dense vector of objective coefficients |
966 | double * objective_; |
967 | |
968 | /// Constant offset for objective value (i.e., RHS value for OBJ row) |
969 | double objectiveOffset_; |
970 | |
971 | |
972 | /** Pointer to dense vector specifying if a variable is continuous |
973 | (0) or integer (1). |
974 | */ |
975 | char * integerType_; |
976 | |
977 | /** Row and column names |
978 | Linked to hash table sections (0 - row names, 1 column names) |
979 | */ |
980 | char **names_[2]; |
981 | //@} |
982 | |
983 | /** @name Hash tables */ |
984 | //@{ |
985 | /// Current file name |
986 | char * fileName_; |
987 | |
988 | /// Number of entries in a hash table section |
989 | int numberHash_[2]; |
990 | |
991 | /// Hash tables (two sections, 0 - row names, 1 - column names) |
992 | mutable CoinHashLink *hash_[2]; |
993 | //@} |
994 | |
995 | /** @name CoinMpsIO object parameters */ |
996 | //@{ |
997 | /// Upper bound when no bounds for integers |
998 | int defaultBound_; |
999 | |
1000 | /// Value to use for infinity |
1001 | double infinity_; |
1002 | /// Small element value |
1003 | double smallElement_; |
1004 | |
1005 | /// Message handler |
1006 | CoinMessageHandler * handler_; |
1007 | /** Flag to say if the message handler is the default handler. |
1008 | |
1009 | If true, the handler will be destroyed when the CoinMpsIO |
1010 | object is destroyed; if false, it will not be destroyed. |
1011 | */ |
1012 | bool defaultHandler_; |
1013 | /// Messages |
1014 | CoinMessages messages_; |
1015 | /// Card reader |
1016 | CoinMpsCardReader * cardReader_; |
1017 | /// If .gms file should it be massaged to move objective |
1018 | bool convertObjective_; |
1019 | /// Whether to allow string elements |
1020 | int allowStringElements_; |
1021 | /// Maximum number of string elements |
1022 | int maximumStringElements_; |
1023 | /// Number of string elements |
1024 | int numberStringElements_; |
1025 | /// String elements |
1026 | char ** stringElements_; |
1027 | //@} |
1028 | |
1029 | }; |
1030 | |
1031 | //############################################################################# |
1032 | /** A function that tests the methods in the CoinMpsIO class. The |
1033 | only reason for it not to be a member method is that this way it doesn't |
1034 | have to be compiled into the library. And that's a gain, because the |
1035 | library should be compiled with optimization on, but this method should be |
1036 | compiled with debugging. Also, if this method is compiled with |
1037 | optimization, the compilation takes 10-15 minutes and the machine pages |
1038 | (has 256M core memory!)... */ |
1039 | void |
1040 | CoinMpsIOUnitTest(const std::string & mpsDir); |
1041 | // Function to return number in most efficient way |
1042 | // section is 0 for columns, 1 for rhs,ranges and 2 for bounds |
1043 | /* formatType is |
1044 | 0 - normal and 8 character names |
1045 | 1 - extra accuracy |
1046 | 2 - IEEE hex - INTEL |
1047 | 3 - IEEE hex - not INTEL |
1048 | */ |
1049 | void |
1050 | CoinConvertDouble(int section, int formatType, double value, char outputValue[24]); |
1051 | |
1052 | #endif |
1053 | |