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