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