Scippy

SoPlex

Sequential object-oriented simPlex

spxlpbase_rational.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file spxlpbase_rational.cpp
17  * @brief Saving LPs with Rational values in a form suitable for SoPlex.
18  */
19 
20 #ifndef SOPLEX_LEGACY
21 #include <assert.h>
22 #include <stdio.h>
23 #include <ctype.h>
24 #include <iostream>
25 
26 #include "spxdefines.h"
27 #include "spxlpbase.h"
28 #include "spxout.h"
29 #include "mpsinput.h"
30 #include "exceptions.h"
31 
32 #define MAX_LINE_WRITE_LEN 65536 ///< maximum length allowed for writing lines
33 
34 namespace soplex
35 {
36 // ---------------------------------------------------------------------------------------------------------------------
37 // Specialization for reading LP format
38 // ---------------------------------------------------------------------------------------------------------------------
39 
40 #define LPF_MAX_LINE_LEN 8192 ///< maximum length of a line (8190 + \\n + \\0)
41 
42 /// Is \p c a \c space, \c tab, \c nl or \c cr ?
43 static inline bool LPFisSpace(int c)
44 {
45  return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
46 }
47 
48 
49 
50 /// Is there a number at the beginning of \p s ?
51 static bool LPFisValue(const char* s)
52 {
53  return ((*s >= '0') && (*s <= '9')) || (*s == '+') || (*s == '-') || (*s == '.');
54 }
55 
56 
57 
58 /// Is there a possible column name at the beginning of \p s ?
59 static bool LPFisColName(const char* s)
60 {
61  // strchr() gives a true for the null char.
62  if( *s == '\0' )
63  return false;
64 
65  return ((*s >= 'A') && (*s <= 'Z'))
66  || ((*s >= 'a') && (*s <= 'z'))
67  || (strchr("!\"#$%&()/,;?@_'`{}|~", *s) != 0);
68 }
69 
70 
71 
72 /// Is there a comparison operator at the beginning of \p s ?
73 static bool LPFisSense(const char* s)
74 {
75  return (*s == '<') || (*s == '>') || (*s == '=');
76 }
77 
78 
79 
80 static bool LPFisInfinity(const char* s)
81 {
82  return ((s[0] == '-') || (s[0] == '+'))
83  && (tolower(s[1]) == 'i')
84  && (tolower(s[2]) == 'n')
85  && (tolower(s[3]) == 'f');
86 }
87 
88 
89 
90 static bool LPFisFree(const char* s)
91 {
92  return (tolower(s[0]) == 'f')
93  && ( tolower(s[1]) == 'r')
94  && ( tolower(s[2]) == 'e')
95  && ( tolower(s[3]) == 'e');
96 }
97 
98 
99 
100 /// Read the next number and advance \p pos.
101 /** If only a sign is encountered, the number is assumed to be \c sign * 1. This routine will not catch malformatted
102  * numbers like .e10 !
103  */
104 static Rational LPFreadValue(char*& pos, SPxOut* spxout, const int lineno = -1)
105 {
106  assert(LPFisValue(pos));
107 
108  char tmp[LPF_MAX_LINE_LEN];
109  const char* s = pos;
110  char* t;
111  Rational value = 1;
112  bool has_digits = false;
113  bool has_emptyexponent = false;
114  bool has_dot = false;
115  bool has_exponent = false;
116  bool has_emptydivisor = false;
117 
118  // 1. sign
119  if( (*s == '+') || (*s == '-') )
120  s++;
121 
122  // 2. Digits before the decimal dot
123  while( (*s >= '0') && (*s <= '9') )
124  {
125  has_digits = true;
126  s++;
127  }
128 
129  // 3. Decimal dot
130  if( *s == '.' )
131  {
132  has_dot = true;
133  s++;
134 
135  // 4. If there was a dot, possible digit behind it
136  while( (*s >= '0') && (*s <= '9') )
137  {
138  has_digits = true;
139  s++;
140  }
141  }
142 
143  // 5. Exponent
144  if( tolower(*s) == 'e' )
145  {
146  has_exponent = true;
147  has_emptyexponent = true;
148  s++;
149 
150  // 6. Exponent sign
151  if( (*s == '+') || (*s == '-') )
152  s++;
153 
154  // 7. Exponent digits
155  while( (*s >= '0') && (*s <= '9') )
156  {
157  has_emptyexponent = false;
158  s++;
159  }
160  }
161 
162  // 8. Division
163  if( *s == '/' )
164  {
165  s++;
166  has_emptydivisor = true;
167  while( (*s >= '0') && (*s <= '9') )
168  {
169  has_emptydivisor = false;
170  s++;
171  }
172  if( has_dot || has_exponent || has_emptydivisor ||
173  (*s == '.') ||(*s == '+') || (*s == '-') || (tolower(*s) == 'e') )
174  {
175  MSG_WARNING( (*spxout), (*spxout) << "WLPFRD03 Warning: In line " << lineno << ": malformed rational value in LP file\n";)
176  }
177  }
178 
179 
180  assert(s != pos);
181 
182  if( has_emptyexponent )
183  {
184  MSG_WARNING( (*spxout), (*spxout) << "WLPFRD01 Warning: In line " << lineno << ": found empty exponent in LP file - check for forbidden variable names with initial 'e' or 'E'\n" );
185  }
186 
187  if( !has_digits )
188  value = (*pos == '-') ? -1 : 1;
189  else
190  {
191  for( t = tmp; pos != s; pos++ )
192  *t++ = *pos;
193  *t = '\0';
194 
195  if( !value.readString(tmp) )
196  {
197  MSG_WARNING( (*spxout), (*spxout) <<"WLPFRD04 Warning: In line " << lineno << ": malformed rational value in LP file\n" );
198  }
199  }
200  pos += s - pos;
201 
202  assert(pos == s);
203 
204  MSG_DEBUG( std::cout << "DLPFRD01 LPFreadValue = " << value << std::endl; )
205 
206  if( LPFisSpace(*pos) )
207  pos++;
208 
209  return value;
210 }
211 
212 
213 
214 /// Read the next column name from the input.
215 /** The name read is looked up and if not found \p emptycol
216  * is added to \p colset. \p pos is advanced behind the name.
217  * @return The Index of the named column.
218  */
219 static int LPFreadColName(char*& pos, NameSet* colnames, LPColSetBase<Rational>& colset, const LPColBase<Rational>* emptycol, SPxOut* spxout)
220 {
221  assert(LPFisColName(pos));
222  assert(colnames != 0);
223 
224  char name[LPF_MAX_LINE_LEN];
225  const char* s = pos;
226  int i;
227  int colidx;
228 
229  // These are the characters that are not allowed in a column name.
230  while( (strchr("+-.<>= ", *s) == 0) && (*s != '\0') )
231  s++;
232 
233  for( i = 0; pos != s; i++, pos++ )
234  name[i] = *pos;
235 
236  name[i] = '\0';
237 
238  if( (colidx = colnames->number(name)) < 0 )
239  {
240  // We only add the name if we got an empty column.
241  if( emptycol == 0 )
242  MSG_WARNING( (*spxout), (*spxout) << "WLPFRD02 Unknown variable \"" << name << "\" "; )
243  else
244  {
245  colidx = colnames->num();
246  colnames->add(name);
247  colset.add(*emptycol);
248  }
249  }
250 
251  MSG_DEBUG( std::cout << "DLPFRD03 LPFreadColName [" << name << "] = " << colidx << std::endl; )
252 
253  if( LPFisSpace(*pos) )
254  pos++;
255 
256  return colidx;
257 }
258 
259 
260 
261 /// Read the next <,>,=,==,<=,=<,>=,=> and advance \p pos.
262 static int LPFreadSense(char*& pos)
263 {
264  assert(LPFisSense(pos));
265 
266  int sense = *pos++;
267 
268  if( (*pos == '<') || (*pos == '>') )
269  sense = *pos++;
270  else if( *pos == '=' )
271  pos++;
272 
273  MSG_DEBUG( std::cout << "DLPFRD04 LPFreadSense = " << static_cast<char>(sense) << std::endl; )
274 
275  if( LPFisSpace(*pos) )
276  pos++;
277 
278  return sense;
279 }
280 
281 
282 
283 /// Is the \p keyword present in \p buf ? If yes, advance \p pos.
284 /** \p keyword should be lower case. It can contain optional sections which are enclosed in '[' ']' like "min[imize]".
285  */
286 static bool LPFhasKeyword(char*& pos, const char* keyword)
287 {
288  int i;
289  int k;
290 
291  assert(keyword != 0);
292 
293  for( i = 0, k = 0; keyword[i] != '\0'; i++, k++ )
294  {
295  if( keyword[i] == '[' )
296  {
297  i++;
298 
299  // Here we assumed that we have a ']' for the '['.
300  while( (tolower(pos[k]) == keyword[i]) && (pos[k] != '\0') )
301  {
302  k++;
303  i++;
304  }
305  while( keyword[i] != ']' )
306  i++;
307  --k;
308  }
309  else
310  {
311  if( keyword[i] != tolower(pos[k]) )
312  break;
313  }
314  }
315 
316  // we have to be at the end of the keyword and the word found on the line also has to end here. Attention: The
317  // LPFisSense is a kludge to allow LPFhasKeyword also to process Inf[inity] keywords in the bounds section.
318  if( keyword[i] == '\0' && (pos[k] == '\0' || LPFisSpace(pos[k]) || LPFisSense(&pos[k])) )
319  {
320  pos += k;
321 
322  MSG_DEBUG( std::cout << "DLPFRD05 LPFhasKeyword: " << keyword << std::endl; )
323 
324  return true;
325  }
326 
327  return false;
328 }
329 
330 
331 
332 /// If \p buf start with "name:" store the name in \p rownames and advance \p pos.
333 static bool LPFhasRowName(char*& pos, NameSet* rownames)
334 {
335  const char* s = strchr(pos, ':');
336 
337  if( s == 0 )
338  return false;
339 
340  int dcolpos = int(s - pos);
341 
342  int end;
343  int srt;
344 
345  // skip spaces between name and ":"
346  for( end = dcolpos-1; end >= 0; end-- )
347  if( pos[end] != ' ')
348  break;
349 
350  // are there only spaces in front of the ":" ?
351  if( end < 0 )
352  {
353  pos = &(pos[dcolpos+1]);
354  return false;
355  }
356 
357  // skip spaces in front of name
358  for( srt = end-1; srt >= 0; srt-- )
359  if( pos[srt] == ' ' )
360  break;
361 
362  // go back to the non-space character
363  srt++;
364 
365  assert(srt <= end && pos[srt] != ' ');
366 
367  char name[LPF_MAX_LINE_LEN];
368  int i;
369  int k = 0;
370 
371  for( i = srt; i <= end; i++ )
372  name[k++] = pos[i];
373 
374  name[k] = '\0';
375 
376  if( rownames != 0 )
377  rownames->add(name);
378 
379  pos = &(pos[dcolpos+1]);
380 
381  return true;
382 }
383 
384 
385 
386 static Rational LPFreadInfinity(char*& pos)
387 {
388  assert(LPFisInfinity(pos));
389 
390  Rational sense = (*pos == '-') ? -1 : 1;
391 
392  (void) LPFhasKeyword(++pos, "inf[inity]");
393 
394  sense *= Rational(infinity);
395  return sense;
396 }
397 
398 
399 
400 /// Read LP in "CPLEX LP File Format".
401  /** The specification is taken from the ILOG CPLEX 7.0 Reference Manual, Appendix E, Page 527.
402  *
403  * This routine should read (most?) valid LP format files. What it will not do, is find all cases where a file is ill
404  * formed. If this happens it may complain and read nothing or read "something".
405  *
406  * Problem: A line ending in '+' or '-' followed by a line starting with a number, will be regarded as an error.
407  *
408  * The reader will accept the keyword INT[egers] as a synonym for GEN[erals] which is an undocumented feature in CPLEX.
409  *
410  * A difference to the CPLEX reader, is that no name for the objective row is required.
411  *
412  * The manual says the maximum allowed line length is 255 characters, but CPLEX does not complain if the lines are
413  * longer.
414  *
415  * @return true if the file was read correctly
416  */
417 template <>
419  std::istream& p_input, ///< input stream.
420  NameSet* p_rnames, ///< row names.
421  NameSet* p_cnames, ///< column names.
422  DIdxSet* p_intvars) ///< integer variables.
423 {
424  enum
425  {
426  START, OBJECTIVE, CONSTRAINTS, BOUNDS, INTEGERS, BINARIES
427  } section = START;
428 
429  NameSet* rnames; ///< row names.
430  NameSet* cnames; ///< column names.
431 
432  LPColSetBase<Rational> cset; ///< the set of columns read.
433  LPRowSetBase<Rational> rset; ///< the set of rows read.
434  LPColBase<Rational> emptycol; ///< reusable empty column.
435  LPRowBase<Rational> row; ///< last assembled row.
436  DSVectorBase<Rational> vec; ///< last assembled vector (from row).
437 
438  Rational val = 1;
439  int colidx;
440  int sense = 0;
441 
442  char buf[LPF_MAX_LINE_LEN];
443  char tmp[LPF_MAX_LINE_LEN];
444  char line[LPF_MAX_LINE_LEN];
445  int lineno = 0;
446  bool unnamed = true;
447  bool finished = false;
448  bool other;
449  bool have_value = true;
450  int i;
451  int k;
452  char* s;
453  char* pos;
454  char* pos_old = 0;
455 
456  if( p_cnames )
457  cnames = p_cnames;
458  else
459  {
460  cnames = 0;
461  spx_alloc(cnames);
462  cnames = new (cnames) NameSet();
463  }
464 
465  cnames->clear();
466 
467  if( p_rnames )
468  rnames = p_rnames;
469  else
470  {
471  try
472  {
473  rnames = 0;
474  spx_alloc(rnames);
475  rnames = new (rnames) NameSet();
476  }
477  catch( const SPxMemoryException& x )
478  {
479  if( !p_cnames )
480  {
481  cnames->~NameSet();
482  spx_free(cnames);
483  }
484  throw x;
485  }
486  }
487 
488  rnames->clear();
489 
490  SPxLPBase<Rational>::clear(); // clear the LP.
491 
492  //--------------------------------------------------------------------------
493  //--- Main Loop
494  //--------------------------------------------------------------------------
495  for(;;)
496  {
497  // 0. Read a line from the file.
498  if( !p_input.getline(buf, sizeof(buf)) )
499  {
500  if( strlen(buf) == LPF_MAX_LINE_LEN - 1 )
501  {
502  MSG_ERROR( std::cerr << "ELPFRD06 Line exceeds " << LPF_MAX_LINE_LEN - 2
503  << " characters" << std::endl; )
504  }
505  else
506  {
507  MSG_ERROR( std::cerr << "ELPFRD07 No 'End' marker found" << std::endl; )
508  finished = true;
509  }
510  break;
511  }
512  lineno++;
513  i = 0;
514  pos = buf;
515 
516  MSG_DEBUG( std::cout << "DLPFRD08 Reading line " << lineno
517  << " (pos=" << pos << ")" << std::endl; )
518 
519  // 1. Remove comments.
520  if( 0 != (s = strchr(buf, '\\')) )
521  *s = '\0';
522 
523  // 2. Look for keywords.
524  if( section == START )
525  {
526  if( LPFhasKeyword(pos, "max[imize]") )
527  {
528  changeSense(SPxLPBase<Rational>::MAXIMIZE);
529  section = OBJECTIVE;
530  }
531  else if( LPFhasKeyword(pos, "min[imize]") )
532  {
533  changeSense(SPxLPBase<Rational>::MINIMIZE);
534  section = OBJECTIVE;
535  }
536  }
537  else if( section == OBJECTIVE )
538  {
539  if( LPFhasKeyword(pos, "s[ubject][ ]t[o]")
540  || LPFhasKeyword(pos, "s[uch][ ]t[hat]")
541  || LPFhasKeyword(pos, "s[.][ ]t[.]")
542  || LPFhasKeyword(pos, "lazy con[straints]") )
543  {
544  // store objective vector
545  for( int j = vec.size() - 1; j >= 0; --j )
546  cset.maxObj_w(vec.index(j)) = vec.value(j);
547  // multiplication with -1 for minimization is done below
548  vec.clear();
549  have_value = true;
550  val = 1;
551  section = CONSTRAINTS;
552  }
553  }
554  else if( section == CONSTRAINTS &&
555  (LPFhasKeyword(pos, "s[ubject][ ]t[o]")
556  || LPFhasKeyword(pos, "s[uch][ ]t[hat]")
557  || LPFhasKeyword(pos, "s[.][ ]t[.]")) )
558  {
559  have_value = true;
560  val = 1;
561  }
562  else
563  {
564  if( LPFhasKeyword(pos, "lazy con[straints]") )
565  ;
566  else if( LPFhasKeyword(pos, "bound[s]") )
567  section = BOUNDS;
568  else if( LPFhasKeyword(pos, "bin[ary]") )
569  section = BINARIES;
570  else if( LPFhasKeyword(pos, "bin[aries]") )
571  section = BINARIES;
572  else if( LPFhasKeyword(pos, "gen[erals]") )
573  section = INTEGERS;
574  else if( LPFhasKeyword(pos, "int[egers]") ) // this is undocumented
575  section = INTEGERS;
576  else if( LPFhasKeyword(pos, "end") )
577  {
578  finished = true;
579  break;
580  }
581  else if( LPFhasKeyword(pos, "s[ubject][ ]t[o]") // second time
582  || LPFhasKeyword(pos, "s[uch][ ]t[hat]")
583  || LPFhasKeyword(pos, "s[.][ ]t[.]")
584  || LPFhasKeyword(pos, "lazy con[straints]") )
585  {
586  // In principle this has to checked for all keywords above,
587  // otherwise we just ignore any half finished constraint
588  if( have_value )
589  goto syntax_error;
590 
591  have_value = true;
592  val = 1;
593  }
594  }
595 
596  // 3a. Look for row names in objective and drop it.
597  if( section == OBJECTIVE )
598  LPFhasRowName(pos, 0);
599 
600  // 3b. Look for row name in constraint and store it.
601  if( section == CONSTRAINTS )
602  if( LPFhasRowName(pos, rnames) )
603  unnamed = false;
604 
605  // 4a. Remove initial spaces.
606  while( LPFisSpace(pos[i]) )
607  i++;
608 
609  // 4b. remove spaces if they do not appear before the name of a vaiable.
610  for( k = 0; pos[i] != '\0'; i++ )
611  if( !LPFisSpace(pos[i]) || LPFisColName(&pos[i + 1]) )
612  tmp[k++] = pos[i];
613 
614  tmp[k] = '\0';
615 
616  // 5. Is this an empty line ?
617  if( tmp[0] == '\0' )
618  continue;
619 
620  // 6. Collapse sequences of '+' and '-'. e.g ++---+ => -
621  for( i = 0, k = 0; tmp[i] != '\0'; i++ )
622  {
623  while( ((tmp[i] == '+') || (tmp[i] == '-')) && ((tmp[i + 1] == '+') || (tmp[i + 1] == '-')) )
624  {
625  if( tmp[i++] == '-' )
626  tmp[i] = (tmp[i] == '-') ? '+' : '-';
627  }
628  line[k++] = tmp[i];
629  }
630  line[k] = '\0';
631 
632  //-----------------------------------------------------------------------
633  //--- Line processing loop
634  //-----------------------------------------------------------------------
635  pos = line;
636 
637  MSG_DEBUG( std::cout << "DLPFRD09 pos=" << pos << std::endl; )
638 
639  // 7. We have something left to process.
640  while( (pos != 0) && (*pos != '\0') )
641  {
642  // remember our position, so we are sure we make progress.
643  pos_old = pos;
644 
645  // now process the sections
646  switch( section )
647  {
648  case OBJECTIVE:
649  if( LPFisValue(pos) )
650  {
651  Rational pre_sign = 1;
652 
653  /* Already having here a value could only result from being the first number in a constraint, or a sign
654  * '+' or '-' as last token on the previous line.
655  */
656  if( have_value )
657  {
658  if( spxAbs(val) != 1 )
659  goto syntax_error;
660 
661  if( val == -1 )
662  pre_sign = val;
663  }
664  have_value = true;
665  val = LPFreadValue(pos, spxout, lineno);
666  val *= pre_sign;
667  }
668  if( *pos == '\0' )
669  continue;
670 
671  if( !have_value || !LPFisColName(pos) )
672  goto syntax_error;
673 
674  have_value = false;
675  colidx = LPFreadColName(pos, cnames, cset, &emptycol, spxout);
676  vec.add(colidx, val);
677  break;
678  case CONSTRAINTS:
679  if( LPFisValue(pos) )
680  {
681  Rational pre_sign = 1;
682 
683  /* Already having here a value could only result from being the first number in a constraint, or a sign
684  * '+' or '-' as last token on the previous line.
685  */
686  if( have_value )
687  {
688  if( spxAbs(val) != 1 )
689  goto syntax_error;
690 
691  if( val == -1 )
692  pre_sign = val;
693  }
694 
695  have_value = true;
696  val = LPFreadValue(pos, spxout, lineno);
697  val *= pre_sign;
698 
699  if( sense != 0 )
700  {
701  if( sense == '<' )
702  {
703  row.setLhs(-infinity);
704  row.setRhs(val);
705  }
706  else if( sense == '>' )
707  {
708  row.setLhs(val);
709  row.setRhs(infinity);
710  }
711  else
712  {
713  assert(sense == '=');
714 
715  row.setLhs(val);
716  row.setRhs(val);
717  }
718  row.setRowVector(vec);
719  rset.add(row);
720  vec.clear();
721 
722  if( !unnamed )
723  unnamed = true;
724  else
725  {
726  char name[16];
727  sprintf(name, "C%d", rset.num());
728  rnames->add(name);
729  }
730  have_value = true;
731  val = 1;
732  sense = 0;
733  pos = 0;
734  // next line
735  continue;
736  }
737  }
738  if( *pos == '\0' )
739  continue;
740 
741  if( have_value )
742  {
743  if( LPFisColName(pos) )
744  {
745  colidx = LPFreadColName(pos, cnames, cset, &emptycol, spxout);
746 
747  if( val != 0 )
748  {
749  // Do we have this index already in the row?
750  int n = vec.number(colidx);
751 
752  // if not, add it
753  if( n < 0 )
754  vec.add(colidx, val);
755  // if yes, add them up and remove the element if it amounts to zero
756  else
757  {
758  assert(vec.index(n) == colidx);
759 
760  val += vec.value(n);
761 
762  if( val == 0 )
763  vec.remove(n);
764  else
765  vec.value(n) = val;
766 
767  assert(cnames->has(colidx));
768 
769  MSG_WARNING( (*spxout), (*spxout) << "WLPFRD10 Duplicate index "
770  << (*cnames)[colidx]
771  << " in line " << lineno
772  << std::endl; )
773  }
774  }
775  have_value = false;
776  }
777  else
778  {
779  // We have a row like c1: <= 5 with no variables. We can not handle 10 <= 5; issue a syntax error.
780  if( val != 1 )
781  goto syntax_error;
782 
783  // If the next thing is not the sense we give up also.
784  if( !LPFisSense(pos) )
785  goto syntax_error;
786 
787  have_value = false;
788  }
789  }
790  assert(!have_value);
791 
792  if( LPFisSense(pos) )
793  sense = LPFreadSense(pos);
794  break;
795  case BOUNDS:
796  other = false;
797  sense = 0;
798 
799  if( LPFisValue(pos) )
800  {
801  val = LPFisInfinity(pos) ? LPFreadInfinity(pos) : LPFreadValue(pos, spxout, lineno);
802 
803  if( !LPFisSense(pos) )
804  goto syntax_error;
805 
806  sense = LPFreadSense(pos);
807  other = true;
808  }
809 
810  if( !LPFisColName(pos) )
811  goto syntax_error;
812 
813  if( (colidx = LPFreadColName(pos, cnames, cset, 0, spxout)) < 0 )
814  {
815  MSG_WARNING( (*spxout), (*spxout) << "WLPFRD11 in Bounds section line "
816  << lineno << " ignored" << std::endl; )
817  *pos = '\0';
818  continue;
819  }
820 
821  if( sense )
822  {
823  if( sense == '<' )
824  cset.lower_w(colidx) = val;
825  else if( sense == '>' )
826  cset.upper_w(colidx) = val;
827  else
828  {
829  assert(sense == '=');
830  cset.lower_w(colidx) = val;
831  cset.upper_w(colidx) = val;
832  }
833  }
834 
835  if( LPFisFree(pos) )
836  {
837  cset.lower_w(colidx) = -infinity;
838  cset.upper_w(colidx) = infinity;
839  other = true;
840  pos += 4; // set position after the word "free"
841  }
842  else if( LPFisSense(pos) )
843  {
844  sense = LPFreadSense(pos);
845  other = true;
846 
847  if( !LPFisValue(pos) )
848  goto syntax_error;
849 
850  val = LPFisInfinity(pos) ? LPFreadInfinity(pos) : LPFreadValue(pos, spxout, lineno);
851 
852  if( sense == '<' )
853  cset.upper_w(colidx) = val;
854  else if( sense == '>' )
855  cset.lower_w(colidx) = val;
856  else
857  {
858  assert(sense == '=');
859  cset.lower_w(colidx) = val;
860  cset.upper_w(colidx) = val;
861  }
862  }
863 
864  /* Do we have only a single column name in the input line? We could ignore this savely, but it is probably
865  * a sign of some other error.
866  */
867  if( !other )
868  goto syntax_error;
869  break;
870  case BINARIES:
871  case INTEGERS:
872  if( (colidx = LPFreadColName(pos, cnames, cset, 0, spxout)) < 0 )
873  {
874  MSG_WARNING( (*spxout), (*spxout) << "WLPFRD12 in Binary/General section line " << lineno << " ignored" << std::endl; )
875  }
876  else
877  {
878  if( section == BINARIES )
879  {
880  if( cset.lower(colidx) < 0 )
881  {
882  cset.lower_w(colidx) = 0;
883  }
884  if( cset.upper(colidx) > 1 )
885  {
886  cset.upper_w(colidx) = 1;
887  }
888  }
889 
890  if( p_intvars != 0 )
891  p_intvars->addIdx(colidx);
892  }
893  break;
894  case START:
895  MSG_ERROR( std::cerr << "ELPFRD13 This seems to be no LP format file" << std::endl; )
896  goto syntax_error;
897  default:
898  throw SPxInternalCodeException("XLPFRD01 This should never happen.");
899  }
900 
901  if( pos == pos_old )
902  goto syntax_error;
903  }
904  }
905 
906  assert(isConsistent());
907 
908  addCols(cset);
909  assert(isConsistent());
910 
911  addRows(rset);
912  assert(isConsistent());
913 
914 syntax_error:
915  if( finished )
916  {
917  MSG_INFO2( (*spxout), (*spxout) << "Finished reading " << lineno << " lines" << std::endl; )
918  }
919  else
920  MSG_ERROR( std::cerr << "ELPFRD15 Syntax error in line " << lineno << std::endl; )
921 
922  if( p_cnames == 0 )
923  spx_free(cnames);
924  if( p_rnames == 0 )
925  spx_free(rnames);
926 
927  return finished;
928 }
929 
930 
931 
932 // ---------------------------------------------------------------------------------------------------------------------
933 // Specialization for reading MPS format
934 // ---------------------------------------------------------------------------------------------------------------------
935 
936 /// Process NAME section.
937 static void MPSreadName(MPSInput& mps, SPxOut* spxout)
938 {
939  do
940  {
941  // This has to be the Line with the NAME section.
942  if( !mps.readLine() || (mps.field0() == 0) || strcmp(mps.field0(), "NAME") )
943  break;
944 
945  // Sometimes the name is omitted.
946  mps.setProbName((mps.field1() == 0) ? "_MPS_" : mps.field1());
947 
948  MSG_INFO2( (*spxout), (*spxout) << "IMPSRD01 Problem name : " << mps.probName() << std::endl; )
949 
950  // This has to be a new section
951  if( !mps.readLine() || (mps.field0() == 0) )
952  break;
953 
954  if( !strcmp(mps.field0(), "ROWS") )
956  else if( !strncmp(mps.field0(), "OBJSEN", 6) )
958  else if( !strcmp(mps.field0(), "OBJNAME") )
960  else
961  break;
962 
963  return;
964  }
965  while(false);
966 
967  mps.syntaxError();
968 }
969 
970 
971 
972 /// Process OBJSEN section. This Section is an ILOG extension.
973 static void MPSreadObjsen(MPSInput& mps)
974 {
975  do
976  {
977  // This has to be the Line with MIN or MAX.
978  if( !mps.readLine() || (mps.field1() == 0) )
979  break;
980 
981  if( !strcmp(mps.field1(), "MIN") )
983  else if( !strcmp(mps.field1(), "MAX") )
985  else
986  break;
987 
988  // Look for ROWS or OBJNAME Section
989  if( !mps.readLine() || (mps.field0() == 0) )
990  break;
991 
992  if( !strcmp(mps.field0(), "ROWS") )
994  else if( !strcmp(mps.field0(), "OBJNAME") )
996  else
997  break;
998 
999  return;
1000  }
1001  while(false);
1002 
1003  mps.syntaxError();
1004 }
1005 
1006 
1007 
1008 /// Process OBJNAME section. This Section is an ILOG extension.
1009 static void MPSreadObjname(MPSInput& mps)
1010 {
1011  do
1012  {
1013  // This has to be the Line with the name.
1014  if( !mps.readLine() || (mps.field1() == 0) )
1015  break;
1016 
1017  mps.setObjName(mps.field1());
1018 
1019  // Look for ROWS Section
1020  if( !mps.readLine() || (mps.field0() == 0) )
1021  break;
1022 
1023  if( strcmp(mps.field0(), "ROWS") )
1024  break;
1025 
1027 
1028  return;
1029  }
1030  while(false);
1031 
1032  mps.syntaxError();
1033 }
1034 
1035 
1036 
1037 /// Process ROWS section.
1038 static void MPSreadRows(MPSInput& mps, LPRowSetBase<Rational>& rset, NameSet& rnames, SPxOut* spxout)
1039 {
1040  LPRowBase<Rational> row;
1041 
1042  while( mps.readLine() )
1043  {
1044  if( mps.field0() != 0 )
1045  {
1046  MSG_INFO2( (*spxout), (*spxout) << "IMPSRD02 Objective name : " << mps.objName() << std::endl; )
1047 
1048  if( strcmp(mps.field0(), "COLUMNS") )
1049  break;
1050 
1052 
1053  return;
1054  }
1055 
1056  if( *mps.field1() == 'N' )
1057  {
1058  if( *mps.objName() == '\0' )
1059  mps.setObjName(mps.field2());
1060  }
1061  else
1062  {
1063  if( rnames.has(mps.field2()) )
1064  break;
1065 
1066  rnames.add(mps.field2());
1067 
1068  switch( *mps.field1() )
1069  {
1070  case 'G':
1071  row.setLhs(0);
1072  row.setRhs(infinity);
1073  break;
1074  case 'E':
1075  row.setLhs(0);
1076  row.setRhs(0);
1077  break;
1078  case 'L':
1079  row.setLhs(-infinity);
1080  row.setRhs(0);
1081  break;
1082  default:
1083  mps.syntaxError();
1084  return;
1085  }
1086 
1087  rset.add(row);
1088  }
1089 
1090  assert((*mps.field1() == 'N') || (rnames.number(mps.field2()) == rset.num() - 1));
1091  }
1092 
1093  mps.syntaxError();
1094 }
1095 
1096 
1097 
1098 /// Process COLUMNS section.
1099 static void MPSreadCols(MPSInput& mps, const LPRowSetBase<Rational>& rset, const NameSet& rnames, LPColSetBase<Rational>& cset, NameSet& cnames, DIdxSet* intvars, SPxOut* spxout)
1100 {
1101  Rational val;
1102  int idx;
1103  char colname[MPSInput::MAX_LINE_LEN] = { '\0' };
1104  LPColBase<Rational> col(rset.num());
1106 
1107  col.setObj(0);
1108  vec.clear();
1109 
1110  while( mps.readLine() )
1111  {
1112  if( mps.field0() != 0 )
1113  {
1114  if( strcmp(mps.field0(), "RHS") )
1115  break;
1116 
1117  if( colname[0] != '\0' )
1118  {
1119  col.setColVector(vec);
1120  cset.add(col);
1121  }
1122 
1124 
1125  return;
1126  }
1127 
1128  if( (mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0) )
1129  break;
1130 
1131  // new column?
1132  if( strcmp(colname, mps.field1()) )
1133  {
1134  // first column?
1135  if( colname[0] != '\0' )
1136  {
1137  col.setColVector(vec);
1138  cset.add(col);
1139  }
1140 
1141  // save copy of string (make sure string ends with \0)
1142  strncpy(colname, mps.field1(), MPSInput::MAX_LINE_LEN-1);
1143  colname[MPSInput::MAX_LINE_LEN-1] = '\0';
1144  cnames.add(colname);
1145  vec.clear();
1146  col.setObj(0);
1147  col.setLower(0);
1148  col.setUpper(infinity);
1149 
1150  if( mps.isInteger() )
1151  {
1152  assert(cnames.number(colname) == cset.num());
1153 
1154  if( intvars != 0 )
1155  intvars->addIdx(cnames.number(colname));
1156 
1157  // for Integer variable the default bounds are 0/1
1158  col.setUpper(1);
1159  }
1160  }
1161 
1162  if( !val.readString(mps.field3()) )
1163  {
1164  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD01 Warning: malformed rational value in MPS file\n" );
1165  }
1166 
1167 
1168  if( !strcmp(mps.field2(), mps.objName()) )
1169  col.setObj(val);
1170  else
1171  {
1172  if( (idx = rnames.number(mps.field2())) < 0 )
1173  mps.entryIgnored("Column", mps.field1(), "row", mps.field2());
1174  else if( val != 0 )
1175  vec.add(idx, val);
1176  }
1177 
1178  if( mps.field5() != 0 )
1179  {
1180  assert(mps.field4() != 0);
1181 
1182  if( !val.readString(mps.field5()) )
1183  {
1184  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD02 Warning: malformed rational value in MPS file\n" );
1185  }
1186 
1187  if( !strcmp(mps.field4(), mps.objName()) )
1188  col.setObj(val);
1189  else
1190  {
1191  if( (idx = rnames.number(mps.field4())) < 0 )
1192  mps.entryIgnored("Column", mps.field1(), "row", mps.field4());
1193  else if( val != 0 )
1194  vec.add(idx, val);
1195  }
1196  }
1197  }
1198 
1199  mps.syntaxError();
1200 }
1201 
1202 
1203 
1204 /// Process RHS section.
1205 static void MPSreadRhs(MPSInput& mps, LPRowSetBase<Rational>& rset, const NameSet& rnames, SPxOut* spxout)
1206 {
1207  char rhsname[MPSInput::MAX_LINE_LEN] = { '\0' };
1208  char addname[MPSInput::MAX_LINE_LEN] = { '\0' };
1209  int idx;
1210  Rational val;
1211 
1212  while( mps.readLine() )
1213  {
1214  if( mps.field0() != 0 )
1215  {
1216  MSG_INFO2( (*spxout), (*spxout) << "IMPSRD03 RHS name : " << rhsname << std::endl; );
1217 
1218  if( !strcmp(mps.field0(), "RANGES") )
1220  else if( !strcmp(mps.field0(), "BOUNDS") )
1222  else if( !strcmp(mps.field0(), "ENDATA") )
1224  else
1225  break;
1226 
1227  return;
1228  }
1229 
1230  if( ((mps.field2() != 0) && (mps.field3() == 0)) || ((mps.field4() != 0) && (mps.field5() == 0)) )
1231  mps.insertName("_RHS_");
1232 
1233  if( (mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0) )
1234  break;
1235 
1236  if( *rhsname == '\0' )
1237  strcpy(rhsname, mps.field1());
1238 
1239  if( strcmp(rhsname, mps.field1()) )
1240  {
1241  if( strcmp(addname, mps.field1()) )
1242  {
1243  assert(strlen(mps.field1()) < MPSInput::MAX_LINE_LEN);
1244  strcpy(addname, mps.field1());
1245  MSG_INFO3( (*spxout), (*spxout) << "IMPSRD07 RHS ignored : " << addname << std::endl );
1246  }
1247  }
1248  else
1249  {
1250  if( (idx = rnames.number(mps.field2())) < 0 )
1251  mps.entryIgnored("RHS", mps.field1(), "row", mps.field2());
1252  else
1253  {
1254  if( !val.readString(mps.field3()) )
1255  {
1256  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD03 Warning: malformed rational value in MPS file\n" );
1257  }
1258 
1259  // LE or EQ
1260  if( double(rset.rhs(idx)) < double(infinity) )
1261  rset.rhs_w(idx) = val;
1262  // GE or EQ
1263  if( double(rset.lhs(idx)) > double(-infinity) )
1264  rset.lhs_w(idx) = val;
1265  }
1266 
1267  if( mps.field5() != 0 )
1268  {
1269  if( (idx = rnames.number(mps.field4())) < 0 )
1270  mps.entryIgnored("RHS", mps.field1(), "row", mps.field4());
1271  else
1272  {
1273  if( !val.readString(mps.field5()) )
1274  {
1275  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD04 Warning: malformed rational value in MPS file\n" );
1276  }
1277 
1278  // LE or EQ
1279  if( double(rset.rhs(idx)) < double(infinity) )
1280  rset.rhs_w(idx) = val;
1281  // GE or EQ
1282  if( double(rset.lhs(idx)) > double(-infinity) )
1283  rset.lhs_w(idx) = val;
1284  }
1285  }
1286  }
1287  }
1288 
1289  mps.syntaxError();
1290 }
1291 
1292 
1293 
1294 /// Process RANGES section.
1295 static void MPSreadRanges(MPSInput& mps, LPRowSetBase<Rational>& rset, const NameSet& rnames, SPxOut* spxout)
1296 {
1297  char rngname[MPSInput::MAX_LINE_LEN] = { '\0' };
1298  int idx;
1299  Rational val;
1300 
1301  while( mps.readLine() )
1302  {
1303  if( mps.field0() != 0 )
1304  {
1305  MSG_INFO2( (*spxout), (*spxout) << "IMPSRD04 Range name : " << rngname << std::endl; );
1306 
1307  if( !strcmp(mps.field0(), "BOUNDS") )
1309  else if( !strcmp(mps.field0(), "ENDATA") )
1311  else
1312  break;
1313 
1314  return;
1315  }
1316 
1317  if( ((mps.field2() != 0) && (mps.field3() == 0)) || ((mps.field4() != 0) && (mps.field5() == 0)) )
1318  mps.insertName("_RNG_");
1319 
1320  if( (mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0) )
1321  break;
1322 
1323  if( *rngname == '\0' )
1324  {
1325  assert(strlen(mps.field2()) < MPSInput::MAX_LINE_LEN);
1326  strcpy(rngname, mps.field1());
1327  }
1328 
1329  /* The rules are:
1330  * Row Sign LHS RHS
1331  * ----------------------------------------
1332  * G +/- rhs rhs + |range|
1333  * L +/- rhs - |range| rhs
1334  * E + rhs rhs + range
1335  * E - rhs + range rhs
1336  * ----------------------------------------
1337  */
1338  if( !strcmp(rngname, mps.field1()) )
1339  {
1340  if( (idx = rnames.number(mps.field2())) < 0 )
1341  mps.entryIgnored("Range", mps.field1(), "row", mps.field2());
1342  else
1343  {
1344  if( !val.readString(mps.field3()) )
1345  {
1346  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD05 Warning: malformed rational value in MPS file\n" );
1347  }
1348 
1349  // EQ
1350  if( (double(rset.lhs(idx)) > -double(infinity)) && (double(rset.rhs_w(idx)) < double(infinity)) )
1351  {
1352  assert(rset.lhs(idx) == rset.rhs(idx));
1353 
1354  if( double(val) >= 0 )
1355  rset.rhs_w(idx) += val;
1356  else
1357  rset.lhs_w(idx) += val;
1358  }
1359  else
1360  {
1361  // GE
1362  if( double(rset.lhs(idx)) > -double(infinity) )
1363  {
1364  rset.rhs_w(idx) = rset.lhs(idx);
1365  rset.rhs_w(idx) += spxAbs(val);
1366  }
1367  // LE
1368  else
1369  {
1370  rset.lhs_w(idx) = rset.rhs(idx);
1371  rset.lhs_w(idx) -= spxAbs(val);
1372  }
1373  }
1374  }
1375 
1376  if( mps.field5() != 0 )
1377  {
1378  if( (idx = rnames.number(mps.field4())) < 0 )
1379  mps.entryIgnored("Range", mps.field1(), "row", mps.field4());
1380  else
1381  {
1382  if( !val.readString(mps.field5()) )
1383  {
1384  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD06 Warning: malformed rational value in MPS file\n" );
1385  }
1386 
1387  // EQ
1388  if( (double(rset.lhs(idx)) > -double(infinity)) && (double(rset.rhs(idx)) < double(infinity)) )
1389  {
1390  assert(rset.lhs(idx) == rset.rhs(idx));
1391 
1392  if( double(val) >= 0 )
1393  rset.rhs_w(idx) += val;
1394  else
1395  rset.lhs_w(idx) += val;
1396  }
1397  else
1398  {
1399  // GE
1400  if( double(rset.lhs(idx)) > -double(infinity) )
1401  {
1402  rset.rhs_w(idx) = rset.lhs(idx);
1403  rset.rhs_w(idx) += spxAbs(val);
1404  }
1405  // LE
1406  else
1407  {
1408  rset.lhs_w(idx) = rset.rhs(idx);
1409  rset.lhs_w(idx) -= spxAbs(val);
1410  }
1411  }
1412  }
1413  }
1414  }
1415  }
1416 
1417  mps.syntaxError();
1418 }
1419 
1420 
1421 
1422 /// Process BOUNDS section.
1423 static void MPSreadBounds(MPSInput& mps, LPColSetBase<Rational>& cset, const NameSet& cnames, DIdxSet* intvars, SPxOut* spxout)
1424 {
1425  DIdxSet oldbinvars;
1426  char bndname[MPSInput::MAX_LINE_LEN] = { '\0' };
1427  int idx;
1428  Rational val;
1429 
1430  while( mps.readLine() )
1431  {
1432  if( mps.field0() != 0 )
1433  {
1434  MSG_INFO2( (*spxout), (*spxout) << "IMPSRD05 Bound name : " << bndname << std::endl; )
1435 
1436  if( strcmp(mps.field0(), "ENDATA") )
1437  break;
1438 
1440 
1441  return;
1442  }
1443 
1444  // Is the value field used ?
1445  if( (!strcmp(mps.field1(), "LO"))
1446  || (!strcmp(mps.field1(), "UP"))
1447  || (!strcmp(mps.field1(), "FX"))
1448  || (!strcmp(mps.field1(), "LI"))
1449  || (!strcmp(mps.field1(), "UI")) )
1450  {
1451  if( (mps.field3() != 0) && (mps.field4() == 0) )
1452  mps.insertName("_BND_", true);
1453  }
1454  else
1455  {
1456  if( (mps.field2() != 0) && (mps.field3() == 0) )
1457  mps.insertName("_BND_", true);
1458  }
1459 
1460  if( (mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0) )
1461  break;
1462 
1463  if( *bndname == '\0' )
1464  {
1465  assert(strlen(mps.field2()) < MPSInput::MAX_LINE_LEN);
1466  strcpy(bndname, mps.field2());
1467  }
1468 
1469  // Only read the first Bound in section
1470  if( !strcmp(bndname, mps.field2()) )
1471  {
1472  if( (idx = cnames.number(mps.field3())) < 0 )
1473  mps.entryIgnored("column", mps.field3(), "bound", bndname);
1474  else
1475  {
1476  if( mps.field4() == 0 )
1477  val = 0;
1478  else
1479  {
1480  if( !val.readString(mps.field4()) )
1481  {
1482  MSG_WARNING( (*spxout), (*spxout) <<"WMPSRD07 Warning: malformed rational value in MPS file\n" );
1483  }
1484  }
1485 
1486  // ILOG extension (Integer Bound)
1487  if( mps.field1()[1] == 'I' )
1488  {
1489  if( intvars != 0 )
1490  intvars->addIdx(idx);
1491 
1492  // if the variable has appeared in the MARKER section of the COLUMNS section then its default bounds were
1493  // set to 0,1; the first time it is declared integer we need to change to default bounds 0,infinity
1494  if( oldbinvars.number(idx) < 0 )
1495  {
1496  cset.upper_w(idx) = infinity;
1497  oldbinvars.addIdx(idx);
1498  }
1499  }
1500 
1501  switch( *mps.field1() )
1502  {
1503  case 'L':
1504  cset.lower_w(idx) = val;
1505  break;
1506  case 'U':
1507  cset.upper_w(idx) = val;
1508  break;
1509  case 'F':
1510  if( mps.field1()[1] == 'X' )
1511  {
1512  cset.lower_w(idx) = val;
1513  cset.upper_w(idx) = val;
1514  }
1515  else
1516  {
1517  cset.lower_w(idx) = -infinity;
1518  cset.upper_w(idx) = infinity;
1519  }
1520  break;
1521  case 'M':
1522  cset.lower_w(idx) = -infinity;
1523  break;
1524  case 'P':
1525  cset.upper_w(idx) = infinity;
1526  break;
1527  // Ilog extension (Binary)
1528  case 'B':
1529  cset.lower_w(idx) = 0;
1530  cset.upper_w(idx) = 1;
1531 
1532  if( intvars != 0 )
1533  intvars->addIdx(idx);
1534  break;
1535  default:
1536  mps.syntaxError();
1537  return;
1538  }
1539  }
1540  }
1541  }
1542 
1543  mps.syntaxError();
1544 }
1545 
1546 
1547 
1548 /// Read LP in MPS File Format.
1549 /**
1550  * The specification is taken from the IBM Optimization Library Guide and Reference, online available at
1551  * http://www.software.ibm.com/sos/features/libuser.htm and from the ILOG CPLEX 7.0 Reference Manual, Appendix E, Page
1552  * 531.
1553  *
1554  * This routine should read all valid MPS format files. What it will not do, is find all cases where a file is ill
1555  * formed. If this happens it may complain and read nothing or read "something".
1556  *
1557  * @return true if the file was read correctly.
1558  */
1559 #define INIT_COLS 1000 ///< initialy allocated columns.
1560 #define INIT_NZOS 5000 ///< initialy allocated non zeros.
1561 template <>
1563  std::istream& p_input, ///< input stream.
1564  NameSet* p_rnames, ///< row names.
1565  NameSet* p_cnames, ///< column names.
1566  DIdxSet* p_intvars) ///< integer variables.
1567 {
1568  LPRowSetBase<Rational>& rset = *this;
1569  LPColSetBase<Rational>& cset = *this;
1570  NameSet* rnames;
1571  NameSet* cnames;
1572 
1573  if( p_cnames )
1574  cnames = p_cnames;
1575  else
1576  {
1577  cnames = 0;
1578  spx_alloc(cnames);
1579  cnames = new (cnames) NameSet();
1580  }
1581 
1582  cnames->clear();
1583 
1584  if( p_rnames )
1585  rnames = p_rnames;
1586  else
1587  {
1588  try
1589  {
1590  rnames = 0;
1591  spx_alloc(rnames);
1592  rnames = new (rnames) NameSet();
1593  }
1594  catch( const SPxMemoryException& x )
1595  {
1596  if( !p_cnames )
1597  {
1598  cnames->~NameSet();
1599  spx_free(cnames);
1600  }
1601  throw x;
1602  }
1603  }
1604 
1605  rnames->clear();
1606 
1607  SPxLPBase<Rational>::clear(); // clear the LP.
1608 
1609  cset.memRemax(INIT_NZOS);
1610  cset.reMax(INIT_COLS);
1611 
1612  MPSInput mps(p_input);
1613 
1614  MPSreadName(mps, spxout);
1615 
1616  if( mps.section() == MPSInput::OBJSEN )
1617  MPSreadObjsen(mps);
1618 
1619  if( mps.section() == MPSInput::OBJNAME )
1620  MPSreadObjname(mps);
1621 
1622  if( mps.section() == MPSInput::ROWS )
1623  MPSreadRows(mps, rset, *rnames, spxout);
1624 
1625  addedRows(rset.num());
1626 
1627  if( mps.section() == MPSInput::COLUMNS )
1628  MPSreadCols(mps, rset, *rnames, cset, *cnames, p_intvars, spxout);
1629 
1630  if( mps.section() == MPSInput::RHS )
1631  MPSreadRhs(mps, rset, *rnames, spxout);
1632 
1633  if( mps.section() == MPSInput::RANGES )
1634  MPSreadRanges(mps, rset, *rnames, spxout);
1635 
1636  if( mps.section() == MPSInput::BOUNDS )
1637  MPSreadBounds(mps, cset, *cnames, p_intvars, spxout);
1638 
1639  if( mps.section() != MPSInput::ENDATA )
1640  mps.syntaxError();
1641 
1642  if( mps.hasError() )
1643  clear();
1644  else
1645  {
1647 
1648  MSG_INFO2( (*spxout), (*spxout) << "IMPSRD06 Objective sense: " << ((mps.objSense() == MPSInput::MINIMIZE) ? "Minimize\n" : "Maximize\n") );
1649 
1650  added2Set(
1651  *(reinterpret_cast<SVSetBase<Rational>*>(static_cast<LPRowSetBase<Rational>*>(this))),
1652  *(reinterpret_cast<SVSetBase<Rational>*>(static_cast<LPColSetBase<Rational>*>(this))),
1653  cset.num());
1654  addedCols(cset.num());
1655 
1656  assert(isConsistent());
1657  }
1658 
1659  if( p_cnames == 0 )
1660  {
1661  cnames->~NameSet();
1662  spx_free(cnames);
1663  }
1664 
1665  if( p_rnames == 0 )
1666  {
1667  rnames->~NameSet();
1668  spx_free(rnames);
1669  }
1670 
1671  return !mps.hasError();
1672 }
1673 
1674 
1675 
1676 // ---------------------------------------------------------------------------------------------------------------------
1677 // Specialization for writing LP format
1678 // ---------------------------------------------------------------------------------------------------------------------
1679 
1680 // get the name of a row or construct one
1681 static const char* LPFgetRowName(
1682  const SPxLPBase<Rational>& p_lp,
1683  int p_idx,
1684  const NameSet* p_rnames,
1685  char* p_buf,
1686  int p_num_written_rows
1687  )
1688 {
1689  assert(p_buf != 0);
1690  assert(p_idx >= 0);
1691  assert(p_idx < p_lp.nRows());
1692 
1693  if( p_rnames != 0 )
1694  {
1695  DataKey key = p_lp.rId(p_idx);
1696 
1697  if( p_rnames->has(key) )
1698  return (*p_rnames)[key];
1699  }
1700 
1701  sprintf(p_buf, "C%d", p_num_written_rows);
1702 
1703  return p_buf;
1704 }
1705 
1706 
1707 
1708 // get the name of a column or construct one
1709 static const char* getColName(
1710  const SPxLPBase<Rational>& p_lp,
1711  int p_idx,
1712  const NameSet* p_cnames,
1713  char* p_buf
1714  )
1715 {
1716  assert(p_buf != 0);
1717  assert(p_idx >= 0);
1718  assert(p_idx < p_lp.nCols());
1719 
1720  if( p_cnames != 0 )
1721  {
1722  DataKey key = p_lp.cId(p_idx);
1723 
1724  if( p_cnames->has(key) )
1725  return (*p_cnames)[key];
1726  }
1727 
1728  sprintf(p_buf, "x%d", p_idx);
1729 
1730  return p_buf;
1731 }
1732 
1733 
1734 
1735 // write an SVector
1736 #define NUM_ENTRIES_PER_LINE 5
1737 static void LPFwriteSVector(
1738  const SPxLPBase<Rational>& p_lp, ///< the LP
1739  std::ostream& p_output, ///< output stream
1740  const NameSet* p_cnames, ///< column names
1741  const SVectorBase<Rational>& p_svec, ///< vector to write
1742  SPxOut* spxout ///< out stream
1743  )
1744 {
1745 
1746  char name[16];
1747  int num_coeffs = 0;
1748  long long pos;
1749 
1750  pos = p_output.tellp();
1751 
1752  for( int j = 0; j < p_lp.nCols(); ++j )
1753  {
1754  const Rational coeff = p_svec[j];
1755 
1756  if( coeff == 0 )
1757  continue;
1758 
1759  if( num_coeffs == 0 )
1760  p_output << coeff << " " << getColName(p_lp, j, p_cnames, name);
1761  else
1762  {
1763  // insert a line break every NUM_ENTRIES_PER_LINE columns or whenever max line length is nearly exceeded
1764  if( num_coeffs == NUM_ENTRIES_PER_LINE ||
1765  (long long)(p_output.tellp()) - pos + (long long)(rationalToString(coeff, false).length() + 100) > MAX_LINE_WRITE_LEN )
1766  {
1767  num_coeffs = 0;
1768  p_output << "\n\t";
1769  if( (long long)(p_output.tellp()) - pos > MAX_LINE_WRITE_LEN )
1770  {
1771  MSG_WARNING( (*spxout), (*spxout) << "XLPSWR01 Warning: MAX_LINE_WRITE_LEN possibly exceeded when writing LP file\n" );
1772  }
1773  pos = p_output.tellp();
1774  }
1775 
1776  if( coeff < 0 )
1777  p_output << " - " << -coeff;
1778  else
1779  p_output << " + " << coeff;
1780 
1781  p_output << " " << getColName(p_lp, j, p_cnames, name);
1782  }
1783 
1784  ++num_coeffs;
1785  }
1786 }
1787 
1788 
1789 
1790 // write the objective
1791 static void LPFwriteObjective(
1792  const SPxLPBase<Rational>& p_lp, ///< the LP
1793  std::ostream& p_output, ///< output stream
1794  const NameSet* p_cnames, ///< column names
1795  SPxOut* spxout ///< out stream
1796  )
1797 {
1798 
1799  const int sense = p_lp.spxSense();
1800 
1801  p_output << ((sense == SPxLPBase<Rational>::MINIMIZE) ? "Minimize\n" : "Maximize\n");
1802  p_output << " obj: ";
1803 
1804  const VectorBase<Rational>& obj = p_lp.maxObj();
1805  DSVectorBase<Rational> svec(obj.dim());
1806  svec.operator=(obj);
1807  svec *= Rational(sense);
1808  LPFwriteSVector(p_lp, p_output, p_cnames, svec, spxout);
1809  p_output << "\n";
1810 }
1811 
1812 
1813 
1814 // write non-ranged rows
1815 static void LPFwriteRow(
1816  const SPxLPBase<Rational>& p_lp, ///< the LP
1817  std::ostream& p_output, ///< output stream
1818  const NameSet* p_cnames, ///< column names
1819  const SVectorBase<Rational>& p_svec, ///< vector of the row
1820  const Rational& p_lhs, ///< lhs of the row
1821  const Rational& p_rhs, ///< rhs of the row
1822  SPxOut* spxout ///< out stream
1823  )
1824 {
1825 
1826  long long pos;
1827  pos = p_output.tellp();
1828 
1829  LPFwriteSVector(p_lp, p_output, p_cnames, p_svec, spxout);
1830 
1831  long long sidelen;
1832  sidelen = (p_lhs == p_rhs || double(p_lhs) <= double(-infinity)) ? (long long)rationalToString(p_rhs, false).length() : (long long)rationalToString(p_lhs, false).length();
1833 
1834  // insert a line break if max line length is in danger of being exceeded
1835  if( (long long)(p_output.tellp()) - pos + sidelen + (long long)100 > MAX_LINE_WRITE_LEN )
1836  {
1837  p_output << "\n\t";
1838  if( (long long)(p_output.tellp()) - pos > MAX_LINE_WRITE_LEN )
1839  {
1840  MSG_WARNING( (*spxout), (*spxout) << "XLPSWR02 Warning: MAX_LINE_WRITE_LEN possibly exceeded when writing LP file\n" );
1841  }
1842  pos = p_output.tellp();
1843  }
1844 
1845  // write bound value
1846  if( p_lhs == p_rhs )
1847  p_output << " = " << p_rhs;
1848  else if( double(p_lhs) <= double(-infinity) )
1849  p_output << " <= " << p_rhs;
1850  else
1851  {
1852  assert(double(p_rhs) >= double(infinity));
1853  p_output << " >= " << p_lhs;
1854  }
1855 
1856  p_output << "\n";
1857 
1858  if( (long long)(p_output.tellp()) - pos > MAX_LINE_WRITE_LEN )
1859  {
1860  MSG_WARNING( (*spxout), (*spxout) << "XLPSWR03 Warning: MAX_LINE_WRITE_LEN possibly exceeded when writing LP file\n" );
1861  }
1862 }
1863 
1864 
1865 
1866 // write all rows
1867 static void LPFwriteRows(
1868  const SPxLPBase<Rational>& p_lp, ///< the LP
1869  std::ostream& p_output, ///< output stream
1870  const NameSet* p_rnames, ///< row names
1871  const NameSet* p_cnames, ///< column names
1872  SPxOut* spxout ///< out stream
1873  )
1874 {
1875 
1876  char name[16];
1877 
1878  p_output << "Subject To\n";
1879 
1880  int num_written_rows = 0; // num_written_rows > nRows with ranged rows
1881  for( int i = 0; i < p_lp.nRows(); ++i )
1882  {
1883  const Rational lhs = p_lp.lhs(i);
1884  const Rational rhs = p_lp.rhs(i);
1885 
1886  if( double(lhs) > -double(infinity) && double(rhs) < double(infinity) && lhs != rhs )
1887  {
1888  // ranged row -> write two non-ranged rows
1889  p_output << " " << LPFgetRowName(p_lp, i, p_rnames, name, ++num_written_rows) << "_1 : ";
1890  LPFwriteRow(p_lp, p_output, p_cnames, p_lp.rowVector(i), lhs, infinity, spxout);
1891 
1892  p_output << " " << LPFgetRowName(p_lp, i, p_rnames, name, ++num_written_rows) << "_2 : ";
1893  LPFwriteRow(p_lp, p_output, p_cnames, p_lp.rowVector(i), -infinity, rhs, spxout);
1894  }
1895  else
1896  {
1897  p_output << " " << LPFgetRowName(p_lp, i, p_rnames, name, ++num_written_rows) << " : ";
1898  LPFwriteRow(p_lp, p_output, p_cnames, p_lp.rowVector(i), lhs, rhs, spxout);
1899  }
1900  }
1901 }
1902 
1903 
1904 
1905 // write the variable bounds
1906 // (the default bounds 0 <= x <= infinity are not written)
1907 static void LPFwriteBounds(
1908  const SPxLPBase<Rational>& p_lp, ///< the LP to write
1909  std::ostream& p_output, ///< output stream
1910  const NameSet* p_cnames, ///< column names
1911  SPxOut* spxout ///< out stream
1912  )
1913 {
1914 
1915  char name[16];
1916  long long pos;
1917 
1918  pos = p_output.tellp();
1919 
1920  p_output << "Bounds\n";
1921 
1922  for( int j = 0; j < p_lp.nCols(); ++j )
1923  {
1924  const Rational lower = p_lp.lower(j);
1925  const Rational upper = p_lp.upper(j);
1926 
1927  if( lower == upper )
1928  {
1929  p_output << " " << getColName(p_lp, j, p_cnames, name) << " = " << upper << '\n';
1930  }
1931  else if( double(lower) > -double(infinity) )
1932  {
1933  if( double(upper) < double(infinity) )
1934  {
1935  // range bound
1936  if( lower != 0 )
1937  p_output << " " << lower << " <= "
1938  << getColName(p_lp, j, p_cnames, name)
1939  << " <= " << upper << '\n';
1940  else
1941  p_output << " " << getColName(p_lp, j, p_cnames, name)
1942  << " <= " << upper << '\n';
1943  }
1944  else if( lower != 0 )
1945  p_output << " " << lower << " <= "
1946  << getColName(p_lp, j, p_cnames, name)
1947  << '\n';
1948  }
1949  else if( double(upper) < double(infinity) )
1950  p_output << " -Inf <= "
1951  << getColName(p_lp, j, p_cnames, name)
1952  << " <= " << upper << '\n';
1953  else
1954  p_output << " " << getColName(p_lp, j, p_cnames, name)
1955  << " free\n";
1956 
1957  // check if max line length exceeded
1958  if( (long long)(p_output.tellp()) - pos > MAX_LINE_WRITE_LEN )
1959  {
1960  MSG_WARNING( (*spxout), (*spxout) << "XLPSWR04 Warning: MAX_LINE_WRITE_LEN exceeded when writing LP file\n" );
1961  }
1962  pos = p_output.tellp();
1963  }
1964 }
1965 
1966 
1967 
1968 // write the generals section
1969 static void LPFwriteGenerals(
1970  const SPxLPBase<Rational>& p_lp, ///< the LP to write
1971  std::ostream& p_output, ///< output stream
1972  const NameSet* p_cnames, ///< column names
1973  const DIdxSet* p_intvars ///< integer variables
1974  )
1975 {
1976 
1977  char name[16];
1978 
1979  if( p_intvars == NULL || p_intvars->size() <= 0 )
1980  return; // no integer variables
1981 
1982  p_output << "Generals\n";
1983 
1984  for( int j = 0; j < p_lp.nCols(); ++j )
1985  if( p_intvars->number(j) >= 0 )
1986  p_output << " " << getColName(p_lp, j, p_cnames, name) << "\n";
1987 }
1988 
1989 
1990 
1991 /// Write LP in LP Format.
1992 template <>
1994  std::ostream& p_output, ///< output stream
1995  const NameSet* p_rnames, ///< row names
1996  const NameSet* p_cnames, ///< column names
1997  const DIdxSet* p_intvars ///< integer variables
1998  ) const
1999 {
2000 
2001  LPFwriteObjective(*this, p_output, p_cnames, spxout);
2002  LPFwriteRows(*this, p_output, p_rnames, p_cnames, spxout);
2003  LPFwriteBounds(*this, p_output, p_cnames, spxout);
2004  LPFwriteGenerals(*this, p_output, p_cnames, p_intvars);
2005 
2006  p_output << "End" << std::endl;
2007 }
2008 
2009 
2010 
2011 // ---------------------------------------------------------------------------------------------------------------------
2012 // Specialization for writing MPS format
2013 // ---------------------------------------------------------------------------------------------------------------------
2014 
2015 
2016 static void MPSwriteRecord(
2017  std::ostream& os,
2018  const char* indicator,
2019  const char* name,
2020  SPxOut* spxout,
2021  const char* name1 = 0,
2022  const Rational value1 = 0,
2023  const char* name2 = 0,
2024  const Rational value2 = 0
2025  )
2026 {
2027  char buf[81];
2028  long long pos;
2029  pos = os.tellp();
2030  sprintf(buf, " %-2.2s %-8.8s", (indicator == 0) ? "" : indicator, (name == 0) ? "" : name);
2031  os << buf;
2032 
2033  if( name1 != 0 )
2034  {
2035  sprintf(buf, " %-8.8s ", name1);
2036  os << buf << value1;
2037  if( name2 != 0 )
2038  {
2039  sprintf(buf, " %-8.8s ", name2);
2040  os << buf << value2;
2041  }
2042  }
2043  os << std::endl;
2044 
2045  // Warning if line is too long
2046  if( (long long)(os.tellp()) - pos > MAX_LINE_WRITE_LEN )
2047  {
2048  MSG_WARNING( (*spxout), (*spxout) << "XMPSWR04 Warning: MAX_LINE_WRITE_LEN exceeded when writing MPS file\n" );
2049  }
2050 }
2051 
2052 
2053 
2055 {
2056  Rational rhsval;
2057 
2058  if( double(left) > -double(infinity) ) /// This includes ranges
2059  rhsval = left;
2060  else if( double(right) < double(infinity) )
2061  rhsval = right;
2062  else
2063  throw SPxInternalCodeException("XMPSWR01 This should never happen.");
2064 
2065  return rhsval;
2066 }
2067 
2068 
2069 
2070 static const char* MPSgetRowName(
2071  const SPxLPBase<Rational>& lp,
2072  int idx,
2073  const NameSet* rnames,
2074  char* buf
2075  )
2076 {
2077  assert(buf != 0);
2078  assert(idx >= 0);
2079  assert(idx < lp.nRows());
2080 
2081  if( rnames != 0 )
2082  {
2083  DataKey key = lp.rId(idx);
2084 
2085  if( rnames->has(key) )
2086  return (*rnames)[key];
2087  }
2088 
2089  sprintf(buf, "C%d", idx);
2090 
2091  return buf;
2092 }
2093 
2094 
2095 
2096 /// Write LP in MPS format.
2097 /** @note There will always be a BOUNDS section, even if there are no bounds.
2098  */
2099 template <>
2101  std::ostream& p_output, ///< output stream.
2102  const NameSet* p_rnames, ///< row names.
2103  const NameSet* p_cnames, ///< column names.
2104  const DIdxSet* p_intvars ///< integer variables.
2105  ) const
2106 {
2107 
2108  const char* indicator;
2109  char name [16];
2110  char name1[16];
2111  char name2[16];
2112  bool has_ranges = false;
2113  int i;
2114  int k;
2115 
2116  // --- NAME Section ---
2117  p_output << "NAME MPSDATA" << std::endl;
2118 
2119  // --- ROWS Section ---
2120  p_output << "ROWS" << std::endl;
2121 
2122  for( i = 0; i < nRows(); i++ )
2123  {
2124  if( lhs(i) == rhs(i) )
2125  indicator = "E";
2126  else if( (double(lhs(i)) > -double(infinity)) && (double(rhs(i)) < double(infinity)) )
2127  {
2128  indicator = "E";
2129  has_ranges = true;
2130  }
2131  else if( double(lhs(i)) > -double(infinity) )
2132  indicator = "G";
2133  else if( double(rhs(i)) < double(infinity) )
2134  indicator = "L";
2135  else
2136  throw SPxInternalCodeException("XMPSWR02 This should never happen.");
2137 
2138  MPSwriteRecord(p_output, indicator, MPSgetRowName(*this, i, p_rnames, name), spxout);
2139  }
2140 
2141  MPSwriteRecord(p_output, "N", "MINIMIZE", spxout);
2142 
2143  // --- COLUMNS Section ---
2144  p_output << "COLUMNS" << std::endl;
2145 
2146  bool has_intvars = (p_intvars != 0) && (p_intvars->size() > 0);
2147 
2148  for( int j = 0; j < (has_intvars ? 2 : 1); j++ )
2149  {
2150  bool is_intrun = has_intvars && (j == 1);
2151 
2152  if( is_intrun )
2153  p_output << " MARK0001 'MARKER' 'INTORG'" << std::endl;
2154 
2155  for( i = 0; i < nCols(); i++ )
2156  {
2157  bool is_intvar = has_intvars && (p_intvars->number(i) >= 0);
2158 
2159  if( ( is_intrun && !is_intvar) || (!is_intrun && is_intvar) )
2160  continue;
2161 
2162  const SVectorBase<Rational>& col = colVector(i);
2163  int colsize2 = (col.size() / 2) * 2;
2164 
2165  assert(colsize2 % 2 == 0);
2166 
2167  for( k = 0; k < colsize2; k += 2 )
2168  MPSwriteRecord(p_output, 0, getColName(*this, i, p_cnames, name), spxout,
2169  MPSgetRowName(*this, col.index(k), p_rnames, name1), col.value(k),
2170  MPSgetRowName(*this, col.index(k + 1), p_rnames, name2), col.value(k + 1));
2171 
2172  if( colsize2 != col.size() )
2173  MPSwriteRecord(p_output, 0, getColName(*this, i, p_cnames, name), spxout,
2174  MPSgetRowName(*this, col.index(k), p_rnames, name1), col.value(k));
2175 
2176  if( maxObj(i) != 0 )
2177  MPSwriteRecord(p_output, 0, getColName(*this, i, p_cnames, name), spxout, "MINIMIZE", -maxObj(i));
2178  }
2179 
2180  if( is_intrun )
2181  p_output << " MARK0001 'MARKER' 'INTEND'" << std::endl;
2182  }
2183 
2184  // --- RHS Section ---
2185  p_output << "RHS" << std::endl;
2186 
2187  i = 0;
2188  while( i < nRows() )
2189  {
2190  Rational rhsval1 = 0;
2191  Rational rhsval2 = 0;
2192 
2193  for( ; i < nRows(); i++ )
2194  if( (rhsval1 = MPSgetRHS(lhs(i), rhs(i))) != 0 )
2195  break;
2196 
2197  if( i < nRows() )
2198  {
2199  for( k = i + 1; k < nRows(); k++ )
2200  {
2201  if( (rhsval2 = MPSgetRHS(lhs(k), rhs(k))) != 0 )
2202  break;
2203  }
2204 
2205  if( k < nRows() )
2206  {
2207  MPSwriteRecord(p_output, 0, "RHS", spxout, MPSgetRowName(*this, i, p_rnames, name1), rhsval1,
2208  MPSgetRowName(*this, k, p_rnames, name2), rhsval2);
2209  }
2210  else
2211  MPSwriteRecord(p_output, 0, "RHS", spxout, MPSgetRowName(*this, i, p_rnames, name1), rhsval1);
2212 
2213  i = k + 1;
2214  }
2215  }
2216 
2217  // --- RANGES Section ---
2218  if( has_ranges )
2219  {
2220  p_output << "RANGES" << std::endl;
2221 
2222  for( i = 0; i < nRows(); i++ )
2223  {
2224  if( (double(lhs(i)) > -double(infinity)) && (double(rhs(i)) < double(infinity)) )
2225  {
2226  Rational range = rhs(i);
2227  range -= lhs(i);
2228  MPSwriteRecord(p_output, "", "RANGE", spxout, MPSgetRowName(*this, i, p_rnames, name1), range);
2229  }
2230  }
2231  }
2232 
2233  // --- BOUNDS Section ---
2234  p_output << "BOUNDS" << std::endl;
2235 
2236  for( i = 0; i < nCols(); i++ )
2237  {
2238  // skip variables that do not appear in the objective function or any constraint
2239  const SVectorBase<Rational>& col = colVector(i);
2240 
2241  if( col.size() == 0 && maxObj(i) == 0 )
2242  continue;
2243 
2244  if( lower(i) == upper(i) )
2245  {
2246  MPSwriteRecord(p_output, "FX", "BOUND", spxout, getColName(*this, i, p_cnames, name1), lower(i));
2247  continue;
2248  }
2249 
2250  if( (double(lower(i)) <= double(-infinity)) && (double(upper(i)) >= double(infinity)) )
2251  {
2252  MPSwriteRecord(p_output, "FR", "BOUND", spxout, getColName(*this, i, p_cnames, name1));
2253  continue;
2254  }
2255 
2256  if( lower(i) != 0 )
2257  {
2258  if( double(lower(i)) > -double(infinity) )
2259  MPSwriteRecord(p_output, "LO", "BOUND", spxout, getColName(*this, i, p_cnames, name1), lower(i));
2260  else
2261  MPSwriteRecord(p_output, "MI", "BOUND", spxout, getColName(*this, i, p_cnames, name1));
2262  }
2263 
2264  if( has_intvars && (p_intvars->number(i) >= 0) )
2265  {
2266  // Integer variables have default upper bound 1, but we should write
2267  // it nevertheless since CPLEX seems to assume infinity otherwise.
2268  MPSwriteRecord(p_output, "UP", "BOUND", spxout, getColName(*this, i, p_cnames, name1), upper(i));
2269  }
2270  else
2271  {
2272  // Continous variables have default upper bound infinity
2273  if( double(upper(i)) < double(infinity) )
2274  MPSwriteRecord(p_output, "UP", "BOUND", spxout, getColName(*this, i, p_cnames, name1), upper(i));
2275  }
2276  }
2277 
2278  // --- ENDATA Section ---
2279  p_output << "ENDATA" << std::endl;
2280 
2281  // Output warning when writing a maximisation problem
2282  if( spxSense() == SPxLPBase<Rational>::MAXIMIZE )
2283  {
2284  MSG_WARNING( (*spxout), (*spxout) << "XMPSWR03 Warning: objective function inverted when writing maximization problem in MPS file format\n" );
2285  }
2286 }
2287 
2288 
2289 
2290 // ---------------------------------------------------------------------------------------------------------------------
2291 // Explicit instantiation
2292 // ---------------------------------------------------------------------------------------------------------------------
2293 
2294 template class SPxLPBase < Rational >;
2295 } // namespace soplex
2296 #endif
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3925
static int LPFreadColName(char *&pos, NameSet *colnames, LPColSetBase< Rational > &colset, const LPColBase< Rational > *emptycol, SPxOut *spxout)
Read the next column name from the input.
Exception class for things that should NEVER happen.This class is derived from the SoPlex exception b...
Definition: exceptions.h:109
static bool LPFisValue(const char *s)
Is there a number at the beginning of s ?
void memRemax(int newmax)
Resets length of nonzero memory.
Definition: lpcolsetbase.h:523
static void MPSreadRows(MPSInput &mps, LPRowSetBase< Rational > &rset, NameSet &rnames, SPxOut *spxout)
Process ROWS section.
static Rational LPFreadInfinity(char *&pos)
static bool LPFisFree(const char *s)
const VectorBase< R > & lhs() const
Returns the vector of lhs values.
Definition: lprowsetbase.h:93
const VectorBase< R > & maxObj() const
Returns objective vector for maximization problem.
Definition: spxlpbase.h:384
static void MPSreadBounds(MPSInput &mps, LPColSetBase< Rational > &cset, const NameSet &cnames, DIdxSet *intvars, SPxOut *spxout)
Process BOUNDS section.
static const char * MPSgetRowName(const SPxLPBase< Rational > &lp, int idx, const NameSet *rnames, char *buf)
void entryIgnored(const char *what, const char *what_name, const char *entity, const char *entity_name)
Definition: mpsinput.h:205
const char * probName() const
Definition: mpsinput.h:156
Read MPS format files.
int num() const
Returns the number of LPColBases currently in LPColSetBase.
Definition: lpcolsetbase.h:80
static void MPSreadRhs(MPSInput &mps, LPRowSetBase< Rational > &rset, const NameSet &rnames, SPxOut *spxout)
Process RHS section.
Exception classes for SoPlex.
int num() const
Returns the number of LPRowBases in LPRowSetBase.
Definition: lprowsetbase.h:81
const char * field0() const
Definition: mpsinput.h:144
const char * field2() const
Definition: mpsinput.h:148
static void MPSreadObjsen(MPSInput &mps)
Process OBJSEN section. This Section is an ILOG extension.
static void MPSreadCols(MPSInput &mps, const LPRowSetBase< Rational > &rset, const NameSet &rnames, LPColSetBase< Rational > &cset, NameSet &cnames, DIdxSet *intvars, SPxOut *spxout)
Process COLUMNS section.
#define INIT_NZOS
initialy allocated non zeros.
int size() const
Number of used indices.
Definition: svectorbase.h:152
void syntaxError()
Definition: mpsinput.h:198
int num() const
returns nr. of names in NameSet.
Definition: nameset.h:168
static Rational LPFreadValue(char *&pos, SPxOut *spxout, const int lineno=-1)
Read the next number and advance pos.
const VectorBase< R > & lower() const
Returns lower bound vector.
Definition: spxlpbase.h:420
void add(const LPColBase< R > &pcol)
Definition: lpcolsetbase.h:253
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:254
VectorBase< R > & lhs_w()
Returns the vector of lhs values.
Definition: lprowsetbase.h:99
virtual bool readMPS(std::istream &in, NameSet *rowNames=0, NameSet *colNames=0, DIdxSet *intVars=0)
Reads an LP in MPS format from input stream in.
VectorBase< R > & maxObj_w()
Returns vector of objective values w.r.t. maximization.
Definition: lpcolsetbase.h:98
void remove(int n, int m)
Remove nonzeros n thru m.
Definition: svectorbase.h:361
static const char * getColName(const SPxLP *lp, int idx, const NameSet *cnames, char *buf)
Definition: spxbasis.cpp:563
Wrapper for GMP type mpq_class.We wrap mpq_class so that we can replace it by a double type if GMP is...
Definition: rational.h:45
VectorBase< R > & lower_w()
Returns vector of lower bound values.
Definition: lpcolsetbase.h:134
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:402
void add(const LPRowBase< R > &row)
Definition: lprowsetbase.h:319
VectorBase< R > & upper_w()
Returns vector of upper bound values.
Definition: lpcolsetbase.h:170
bool isInteger() const
Definition: mpsinput.h:164
Saving LPs in a form suitable for SoPlex.
Entry identifier class for items of a DataSet.Every item in a DataSet is assigned a DataKey by which ...
Definition: datakey.h:46
#define MAX_LINE_WRITE_LEN
maximum length allowed for writing lines
static void LPFwriteRow(const SPxLPBase< Rational > &p_lp, std::ostream &p_output, const NameSet *p_cnames, const SVectorBase< Rational > &p_svec, const Rational &p_lhs, const Rational &p_rhs, SPxOut *spxout)
Wrapper for different output streams and verbosity levels.
void add(const SVectorBase< S > &vec)
Append nonzeros of sv.
Definition: dsvectorbase.h:216
Section section() const
Definition: mpsinput.h:140
Exception class for out of memory exceptions.This class is derived from the SoPlex exception base cla...
Definition: exceptions.h:70
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
bool readLine()
reads an MPS format data line and parse the fields.
Definition: mpsinput.cpp:57
static bool LPFhasRowName(char *&pos, NameSet *rownames)
If buf start with "name:" store the name in rownames and advance pos.
static void LPFwriteBounds(const SPxLPBase< Rational > &p_lp, std::ostream &p_output, const NameSet *p_cnames, SPxOut *spxout)
#define MSG_INFO2(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO2.
Definition: spxdefines.h:115
static bool LPFisSense(const char *s)
Is there a comparison operator at the beginning of s ?
#define MSG_DEBUG(x)
Definition: spxdefines.h:127
int number(int i) const
returns the position number of index i.
Definition: idxset.cpp:32
int number(int i) const
Number of index i.
Definition: svectorbase.h:185
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:236
SPxRowId rId(int n) const
Returns the row identifier for row n.
Definition: spxlpbase.h:470
bool readString(const char *s)
read Rational from string
Definition: rational.cpp:3459
int size() const
returns the number of used indices.
Definition: idxset.h:124
Wrapper for several output streams. A verbosity level is used to decide which stream to use and wheth...
Definition: spxout.h:63
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:133
void addIdx(int i)
adds index i to the index set
Definition: didxset.h:75
virtual bool readLPF(std::istream &in, NameSet *rowNames=0, NameSet *colNames=0, DIdxSet *intVars=0)
Reads LP in LP format from input stream in.
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:109
const VectorBase< R > & lower() const
Definition: lpcolsetbase.h:128
static void LPFwriteSVector(const SPxLPBase< Rational > &p_lp, std::ostream &p_output, const NameSet *p_cnames, const SVectorBase< Rational > &p_svec, SPxOut *spxout)
virtual void writeMPS(std::ostream &out, const NameSet *rowNames, const NameSet *colNames, const DIdxSet *p_intvars=0) const
Writes a file in MPS format to out.
Dynamic index set.Class DIdxSet provides dynamic IdxSet in the sense, that no restrictions are posed ...
Definition: didxset.h:42
int dim() const
Dimension of vector.
Definition: vectorbase.h:174
void add(const char *str)
Definition: nameset.cpp:25
static void MPSreadRanges(MPSInput &mps, LPRowSetBase< Rational > &rset, const NameSet &rnames, SPxOut *spxout)
Process RANGES section.
void setObjSense(Sense sense)
Definition: mpsinput.h:188
#define NUM_ENTRIES_PER_LINE
(In)equality for LPs.Class LPRowBase provides constraints for linear programs in the form where a is...
Definition: lprowbase.h:45
void setSection(Section p_section)
Definition: mpsinput.h:171
void clear()
removes all names from NameSet.
Definition: nameset.cpp:131
#define INIT_COLS
Read LP in MPS File Format.
void setObjName(const char *p_objname)
Definition: mpsinput.h:182
Debugging, floating point type and parameter definitions.
Set of strings.Class NameSet implements a symbol or name table. It allows to store or remove names (i...
Definition: nameset.h:61
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:127
void setLhs(const R &p_left)
Sets left-hand side value.
Definition: lprowbase.h:209
bool hasError() const
Definition: mpsinput.h:162
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:242
const char * field1() const
Definition: mpsinput.h:146
Everything should be within this namespace.
static void LPFwriteRows(const SPxLPBase< Rational > &p_lp, std::ostream &p_output, const NameSet *p_rnames, const NameSet *p_cnames, SPxOut *spxout)
const char * field3() const
Definition: mpsinput.h:150
static void MPSreadObjname(MPSInput &mps)
Process OBJNAME section. This Section is an ILOG extension.
void clear()
Remove all indices.
Definition: svectorbase.h:396
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:76
virtual void writeLPF(std::ostream &out, const NameSet *rowNames, const NameSet *colNames, const DIdxSet *p_intvars=0) const
void setObj(const R &p_object)
Sets objective value.
Definition: lpcolbase.h:119
SPxColId cId(int n) const
Returns the column identifier for column n.
Definition: spxlpbase.h:476
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:111
void setRowVector(const DSVectorBase< R > &p_vec)
access constraint row vector.
Definition: lprowbase.h:245
const char * field4() const
Definition: mpsinput.h:152
const VectorBase< R > & upper() const
Definition: lpcolsetbase.h:164
int number(const DataKey &pkey) const
returns number of name with DataKey pkey in NameSet.
Definition: nameset.h:212
Set of LP rows.Class LPRowSetBase implements a set of LPRowBase%s. Unless for memory limitations...
Definition: lprowsetbase.h:44
static int LPFreadSense(char *&pos)
Read the next <,>,=,==,<=,=<,>=,=> and advance pos.
SPxSense spxSense() const
Returns the optimization sense.
Definition: spxlpbase.h:438
void setProbName(const char *p_probname)
Definition: mpsinput.h:176
static bool LPFisColName(const char *s)
Is there a possible column name at the beginning of s ?
static void LPFwriteObjective(const SPxLPBase< Rational > &p_lp, std::ostream &p_output, const NameSet *p_cnames, SPxOut *spxout)
static bool LPFhasKeyword(char *&pos, const char *keyword)
Is the keyword present in buf ? If yes, advance pos.
const Real infinity
Definition: spxdefines.cpp:26
const VectorBase< R > & rhs() const
Returns the vector of rhs values.
Definition: lprowsetbase.h:129
static Rational MPSgetRHS(Rational left, Rational right)
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:224
#define LPF_MAX_LINE_LEN
maximum length of a line (8190 + \n + \0)
void insertName(const char *name, bool second=false)
Inserts name as field 1 and shifts all other fields up.
Definition: mpsinput.cpp:250
static bool LPFisSpace(int c)
Is c a space, tab, nl or cr ?
static void MPSwriteRecord(std::ostream &os, const char *indicator, const char *name, SPxOut *spxout, const char *name1=0, const Rational value1=0, const char *name2=0, const Rational value2=0)
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:212
void setColVector(const SVectorBase< R > &p_vec)
Sets constraint column vector.
Definition: lpcolbase.h:154
static void LPFwriteGenerals(const SPxLPBase< Rational > &p_lp, std::ostream &p_output, const NameSet *p_cnames, const DIdxSet *p_intvars)
static const char * LPFgetRowName(const SPxLPBase< Rational > &p_lp, int p_idx, const NameSet *p_rnames, char *p_buf, int p_num_written_rows)
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:3468
const char * field5() const
Definition: mpsinput.h:154
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:117
VectorBase< R > & rhs_w()
Returns the vector of rhs values (writeable).
Definition: lprowsetbase.h:135
virtual void clear()
clears the LP.
Definition: spxlpbase.h:1007
Sense objSense() const
Definition: mpsinput.h:160
void reMax(int newmax=0)
Reallocates memory to be able to store newmax LPColBases.
Definition: lpcolsetbase.h:502
void setRhs(const R &p_right)
Sets right-hand side value.
Definition: lprowbase.h:221
bool has(int pnum) const
does NameSet has a name with number pnum?
Definition: nameset.h:231
~NameSet()
destructor.
Definition: nameset.cpp:259
LP column.Class LPColBase provides a datatype for storing the column of an LP a the form similar to ...
Definition: lpcolbase.h:45
const char * objName() const
Definition: mpsinput.h:158
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
static void MPSreadName(MPSInput &mps, SPxOut *spxout)
Process NAME section.
static bool LPFisInfinity(const char *s)