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