Scippy

SoPlex

Sequential object-oriented simPlex

spxlpbase_real.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_real.cpp
17  * @brief Saving LPs with Real 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 #include "soplex/spxscaler.h"
31 
32 namespace soplex
33 {
34 
35 template<>
37 {
38  MSG_INFO3((*spxout), (*spxout) << "remove persistent scaling of LP" << std::endl;)
39 
40  if(lp_scaler)
41  lp_scaler->unscale(*this);
42  else
43  MSG_INFO3((*spxout), (*spxout) << "no LP scaler available" << std::endl;)
44  }
45 
46 template<>
48  VectorBase<Real>& activity, const bool unscaled) const
49 {
50  if(primal.dim() != nCols())
51  throw SPxInternalCodeException("XSPXLP01 Primal vector for computing row activity has wrong dimension");
52 
53  if(activity.dim() != nRows())
54  throw SPxInternalCodeException("XSPXLP03 Activity vector computing row activity has wrong dimension");
55 
56  int c;
57 
58  for(c = 0; c < nCols() && primal[c] == 0; c++)
59  ;
60 
61  if(c >= nCols())
62  {
63  activity.clear();
64  return;
65  }
66 
67  DSVector tmp(nRows());
68 
69  if(unscaled && _isScaled)
70  {
71  lp_scaler->getColUnscaled(*this, c, tmp);
72  activity = tmp;
73  }
74  else
75  activity = colVector(c);
76 
77  activity *= primal[c];
78  c++;
79 
80  for(; c < nCols(); c++)
81  {
82  if(primal[c] != 0)
83  {
84  if(unscaled && _isScaled)
85  {
86  lp_scaler->getColUnscaled(*this, c, tmp);
87  activity.multAdd(primal[c], tmp);
88  }
89  else
90  activity.multAdd(primal[c], colVector(c));
91  }
92  }
93 }
94 
95 template<>
97  const bool unscaled) const
98 {
99  if(dual.dim() != nRows())
100  throw SPxInternalCodeException("XSPXLP02 Dual vector for computing dual activity has wrong dimension");
101 
102  if(activity.dim() != nCols())
103  throw SPxInternalCodeException("XSPXLP04 Activity vector computing dual activity has wrong dimension");
104 
105  int r;
106 
107  for(r = 0; r < nRows() && dual[r] == 0; r++)
108  ;
109 
110  if(r >= nRows())
111  {
112  activity.clear();
113  return;
114  }
115 
116  DSVector tmp(nCols());
117 
118  if(unscaled && _isScaled)
119  {
120  lp_scaler->getRowUnscaled(*this, r, tmp);
121  activity = tmp;
122  }
123  else
124  activity = rowVector(r);
125 
126  activity *= dual[r];
127  r++;
128 
129  for(; r < nRows(); r++)
130  {
131  if(dual[r] != 0)
132  {
133  if(unscaled && _isScaled)
134  {
135  lp_scaler->getRowUnscaled(*this, r, tmp);
136  activity.multAdd(dual[r], tmp);
137  }
138  else
139  activity.multAdd(dual[r], rowVector(r));
140  }
141  }
142 }
143 
144 template<>
145 Real SPxLPBase<Real>::maxAbsNzo(bool unscaled) const
146 {
147  Real maxi = 0.0;
148 
149  if(unscaled && _isScaled)
150  {
151  assert(lp_scaler != 0);
152 
153  for(int i = 0; i < nCols(); ++i)
154  {
155  Real m = lp_scaler->getColMaxAbsUnscaled(*this, i);
156 
157  if(m > maxi)
158  maxi = m;
159  }
160  }
161  else
162  {
163  for(int i = 0; i < nCols(); ++i)
164  {
165  Real m = colVector(i).maxAbs();
166 
167  if(m > maxi)
168  maxi = m;
169  }
170  }
171 
172  assert(maxi >= 0.0);
173 
174  return maxi;
175 }
176 
177 template<>
178 Real SPxLPBase<Real>::minAbsNzo(bool unscaled) const
179 {
180  Real mini = infinity;
181 
182  if(unscaled && _isScaled)
183  {
184  assert(lp_scaler != 0);
185 
186  for(int i = 0; i < nCols(); ++i)
187  {
188  Real m = lp_scaler->getColMinAbsUnscaled(*this, i);
189 
190  if(m < mini)
191  mini = m;
192  }
193  }
194  else
195  {
196  for(int i = 0; i < nCols(); ++i)
197  {
198  Real m = colVector(i).minAbs();
199 
200  if(m < mini)
201  mini = m;
202  }
203  }
204 
205  assert(mini >= 0.0);
206 
207  return mini;
208 }
209 
210 /// Gets unscaled objective vector.
211 template <>
213 {
214  if(_isScaled)
215  {
216  assert(lp_scaler);
217  lp_scaler->getMaxObjUnscaled(*this, pobj);
218  }
219  else
220  {
222  }
223 
224  if(spxSense() == MINIMIZE)
225  pobj *= -1.0;
226 }
227 
228 /// Gets unscaled row vector of row \p i.
229 template<>
231 {
232  assert(i >= 0 && i < nRows());
233 
234  if(_isScaled)
235  lp_scaler->getRowUnscaled(*this, i, vec);
236  else
238 }
239 
240 /// Gets unscaled right hand side vector.
241 template<>
243 {
244  if(_isScaled)
245  lp_scaler->getRhsUnscaled(*this, vec);
246  else
247  vec = LPRowSetBase<Real>::rhs();
248 }
249 
250 /// Returns unscaled right hand side of row number \p i.
251 template<>
253 {
254  assert(i >= 0 && i < nRows());
255 
256  if(_isScaled)
257  return lp_scaler->rhsUnscaled(*this, i);
258  else
259  return LPRowSetBase<Real>::rhs(i);
260 }
261 
262 /// Returns unscaled right hand side of row with identifier \p id.
263 template<>
265 {
266  assert(id.isValid());
267  return rhsUnscaled(number(id));
268 }
269 
270 /// Returns unscaled left hand side vector.
271 template<>
273 {
274  if(_isScaled)
275  lp_scaler->getLhsUnscaled(*this, vec);
276  else
277  vec = LPRowSetBase<Real>::lhs();
278 }
279 
280 /// Returns unscaled left hand side of row number \p i.
281 template<>
283 {
284  assert(i >= 0 && i < nRows());
285 
286  if(_isScaled)
287  return lp_scaler->lhsUnscaled(*this, i);
288  else
289  return LPRowSetBase<Real>::lhs(i);
290 }
291 
292 /// Returns left hand side of row with identifier \p id.
293 template<>
295 {
296  assert(id.isValid());
297  return lhsUnscaled(number(id));
298 }
299 
300 /// Gets column vector of column \p i.
301 template<>
303 {
304  assert(i >= 0 && i < nCols());
305 
306  if(_isScaled)
307  lp_scaler->getColUnscaled(*this, i, vec);
308  else
310 }
311 
312 /// Gets column vector of column with identifier \p id.
313 template<>
315 {
316  assert(id.isValid());
317  getColVectorUnscaled(number(id), vec);
318 }
319 
320 /// Returns unscaled objective value of column \p i.
321 template<>
323 {
324  assert(i >= 0 && i < nCols());
325  Real res;
326 
327  if(_isScaled)
328  {
329  res = lp_scaler->maxObjUnscaled(*this, i);
330  }
331  else
332  {
333  res = maxObj(i);
334  }
335 
336  if(spxSense() == MINIMIZE)
337  res *= -1;
338 
339  return res;
340 }
341 
342 /// Returns unscaled objective value of column with identifier \p id.
343 template<>
345 {
346  assert(id.isValid());
347  return objUnscaled(number(id));
348 }
349 
350 /// Returns unscaled objective vector for maximization problem.
351 template<>
353 {
354  if(_isScaled)
355  lp_scaler->getMaxObjUnscaled(*this, vec);
356  else
358 }
359 
360 /// Returns unscaled objective value of column \p i for maximization problem.
361 template<>
363 {
364  assert(i >= 0 && i < nCols());
365 
366  if(_isScaled)
367  return lp_scaler->maxObjUnscaled(*this, i);
368  else
369  return LPColSetBase<Real>::maxObj(i);
370 }
371 
372 /// Returns unscaled objective value of column with identifier \p id for maximization problem.
373 template<>
375 {
376  assert(id.isValid());
377  return maxObjUnscaled(number(id));
378 }
379 
380 /// Returns unscaled upper bound vector
381 template<>
383 {
384  if(_isScaled)
385  lp_scaler->getUpperUnscaled(*this, vec);
386  else
388 }
389 
390 /// Returns unscaled upper bound of column \p i.
391 template<>
393 {
394  assert(i >= 0 && i < nCols());
395 
396  if(_isScaled)
397  return lp_scaler->upperUnscaled(*this, i);
398  else
399  return LPColSetBase<Real>::upper(i);
400 }
401 
402 /// Returns unscaled upper bound of column with identifier \p id.
403 template<>
405 {
406  assert(id.isValid());
407  return upperUnscaled(number(id));
408 }
409 
410 /// Returns unscaled lower bound vector.
411 template<>
413 {
414  if(_isScaled)
415  lp_scaler->getLowerUnscaled(*this, vec);
416  else
418 }
419 
420 /// Returns unscaled lower bound of column \p i.
421 template<>
423 {
424  assert(i >= 0 && i < nCols());
425 
426  if(_isScaled)
427  return lp_scaler->lowerUnscaled(*this, i);
428  else
429  return LPColSetBase<Real>::lower(i);
430 }
431 
432 /// Returns unscaled lower bound of column with identifier \p id.
433 template<>
435 {
436  assert(id.isValid());
437  return lowerUnscaled(number(id));
438 }
439 
440 /// Changes objective vector to \p newObj.
441 template<>
442 void SPxLPBase<Real>::changeMaxObj(const VectorBase<Real>& newObj, bool scale)
443 {
444  assert(maxObj().dim() == newObj.dim());
445 
446  if(scale)
447  {
448  assert(_isScaled);
449  assert(lp_scaler);
450  LPColSetBase<Real>::maxObj_w().scaleAssign(LPColSetBase<Real>::scaleExp.get_const_ptr(), newObj);
451  }
452  else
453  LPColSetBase<Real>::maxObj_w() = newObj;
454 
455  assert(isConsistent());
456 }
457 
458 /// Changes vector of lower bounds to \p newLower.
459 template<>
460 void SPxLPBase<Real>::changeLower(const VectorBase<Real>& newLower, bool scale)
461 {
462  assert(lower().dim() == newLower.dim());
463 
464  if(scale)
465  {
466  assert(_isScaled);
467  assert(lp_scaler);
468  LPColSetBase<Real>::lower_w().scaleAssign(LPColSetBase<Real>::scaleExp.get_const_ptr(), newLower,
469  true);
470  }
471  else
472  LPColSetBase<Real>::lower_w() = newLower;
473 
474  assert(isConsistent());
475 }
476 
477 
478 /// Changes vector of upper bounds to \p newUpper.
479 template<>
480 void SPxLPBase<Real>::changeUpper(const VectorBase<Real>& newUpper, bool scale)
481 {
482  assert(upper().dim() == newUpper.dim());
483 
484  if(scale)
485  {
486  assert(_isScaled);
487  assert(lp_scaler);
488  LPColSetBase<Real>::upper_w().scaleAssign(LPColSetBase<Real>::scaleExp.get_const_ptr(), newUpper,
489  true);
490  }
491  else
492  LPColSetBase<Real>::upper_w() = newUpper;
493 
494  assert(isConsistent());
495 }
496 
497 /// Changes left hand side vector for constraints to \p newLhs.
498 template<>
499 void SPxLPBase<Real>::changeLhs(const VectorBase<Real>& newLhs, bool scale)
500 {
501  assert(lhs().dim() == newLhs.dim());
502 
503  if(scale)
504  {
505  assert(_isScaled);
506  assert(lp_scaler);
507  LPRowSetBase<Real>::lhs_w().scaleAssign(LPRowSetBase<Real>::scaleExp.get_const_ptr(), newLhs);
508  }
509  else
510  LPRowSetBase<Real>::lhs_w() = newLhs;
511 
512  assert(isConsistent());
513 }
514 
515 /// Changes right hand side vector for constraints to \p newRhs.
516 template<>
517 void SPxLPBase<Real>::changeRhs(const VectorBase<Real>& newRhs, bool scale)
518 {
519  assert(rhs().dim() == newRhs.dim());
520 
521  if(scale)
522  {
523  assert(_isScaled);
524  assert(lp_scaler);
525  LPRowSetBase<Real>::rhs_w().scaleAssign(LPRowSetBase<Real>::scaleExp.get_const_ptr(), newRhs);
526  }
527  else
528  LPRowSetBase<Real>::rhs_w() = newRhs;
529 
530  assert(isConsistent());
531 }
532 
533 /// Changes LP element (\p i, \p j) to \p val. \p scale determines whether the new data should be scaled
534 template <>
535 void SPxLPBase<Real>::changeElement(int i, int j, const Real& val, bool scale)
536 {
537  if(i < 0 || j < 0)
538  return;
539 
540  SVectorBase<Real>& row = rowVector_w(i);
541  SVectorBase<Real>& col = colVector_w(j);
542 
543  if(isNotZero(val))
544  {
545  Real newVal;
546 
547  if(scale)
548  {
549  assert(_isScaled);
550  assert(lp_scaler);
551  newVal = lp_scaler->scaleElement(*this, i, j, val);
552  }
553  else
554  newVal = val;
555 
556  if(row.pos(j) >= 0 && col.pos(i) >= 0)
557  {
558  row.value(row.pos(j)) = newVal;
559  col.value(col.pos(i)) = newVal;
560  }
561  else
562  {
563  LPRowSetBase<Real>::add2(i, 1, &j, &newVal);
564  LPColSetBase<Real>::add2(j, 1, &i, &newVal);
565  }
566  }
567  else if(row.pos(j) >= 0 && col.pos(i) >= 0)
568  {
569  row.remove(row.pos(j));
570  col.remove(col.pos(i));
571  }
572 
573  assert(isConsistent());
574 }
575 
576 // ---------------------------------------------------------------------------------------------------------------------
577 // Specialization for reading LP format
578 // ---------------------------------------------------------------------------------------------------------------------
579 
580 #define LPF_MAX_LINE_LEN 8192 ///< maximum length of a line (8190 + \\n + \\0)
581 
582 /// Is \p c a \c space, \c tab, \c nl or \c cr ?
583 static inline bool LPFisSpace(int c)
584 {
585  return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
586 }
587 
588 
589 
590 /// Is there a number at the beginning of \p s ?
591 static bool LPFisValue(const char* s)
592 {
593  return ((*s >= '0') && (*s <= '9')) || (*s == '+') || (*s == '-') || (*s == '.');
594 }
595 
596 
597 
598 /// Is there a possible column name at the beginning of \p s ?
599 static bool LPFisColName(const char* s)
600 {
601  // strchr() gives a true for the null char.
602  if(*s == '\0')
603  return false;
604 
605  return ((*s >= 'A') && (*s <= 'Z'))
606  || ((*s >= 'a') && (*s <= 'z'))
607  || (strchr("!\"#$%&()/,;?@_'`{}|~", *s) != 0);
608 }
609 
610 
611 
612 /// Is there a comparison operator at the beginning of \p s ?
613 static bool LPFisSense(const char* s)
614 {
615  return (*s == '<') || (*s == '>') || (*s == '=');
616 }
617 
618 
619 
620 static bool LPFisInfinity(const char* s)
621 {
622  return ((s[0] == '-') || (s[0] == '+'))
623  && (tolower(s[1]) == 'i')
624  && (tolower(s[2]) == 'n')
625  && (tolower(s[3]) == 'f');
626 }
627 
628 
629 
630 static bool LPFisFree(const char* s)
631 {
632  return (tolower(s[0]) == 'f')
633  && (tolower(s[1]) == 'r')
634  && (tolower(s[2]) == 'e')
635  && (tolower(s[3]) == 'e');
636 }
637 
638 
639 
640 /// Read the next number and advance \p pos.
641 /** If only a sign is encountered, the number is assumed to be \c sign * 1.0. This routine will not catch malformatted
642  * numbers like .e10 !
643  */
644 static Real LPFreadValue(char*& pos, SPxOut* spxout)
645 {
646  assert(LPFisValue(pos));
647 
648  char tmp[LPF_MAX_LINE_LEN];
649  const char* s = pos;
650  char* t;
651  Real value = 1.0;
652  bool has_digits = false;
653  bool has_emptyexponent = false;
654 
655  // 1. sign
656  if((*s == '+') || (*s == '-'))
657  s++;
658 
659  // 2. Digits before the decimal dot
660  while((*s >= '0') && (*s <= '9'))
661  {
662  has_digits = true;
663  s++;
664  }
665 
666  // 3. Decimal dot
667  if(*s == '.')
668  {
669  s++;
670 
671  // 4. If there was a dot, possible digit behind it
672  while((*s >= '0') && (*s <= '9'))
673  {
674  has_digits = true;
675  s++;
676  }
677  }
678 
679  // 5. Exponent
680  if(tolower(*s) == 'e')
681  {
682  has_emptyexponent = true;
683  s++;
684 
685  // 6. Exponent sign
686  if((*s == '+') || (*s == '-'))
687  s++;
688 
689  // 7. Exponent digits
690  while((*s >= '0') && (*s <= '9'))
691  {
692  has_emptyexponent = false;
693  s++;
694  }
695  }
696 
697  assert(s != pos);
698 
699  if(has_emptyexponent)
700  {
701  MSG_WARNING((*spxout), (*spxout) <<
702  "WLPFRD01 Warning: found empty exponent in LP file - check for forbidden variable names with initial 'e' or 'E'\n";
703  )
704  }
705 
706  if(!has_digits)
707  value = (*pos == '-') ? -1.0 : 1.0;
708  else
709  {
710  for(t = tmp; pos != s; pos++)
711  *t++ = *pos;
712 
713  *t = '\0';
714  value = atof(tmp);
715  }
716 
717  pos += s - pos;
718 
719  assert(pos == s);
720 
721  MSG_DEBUG(std::cout << "DLPFRD01 LPFreadValue = " << value << std::endl;)
722 
723  if(LPFisSpace(*pos))
724  pos++;
725 
726  return value;
727 }
728 
729 
730 
731 /// Read the next column name from the input.
732 /** The name read is looked up and if not found \p emptycol
733  * is added to \p colset. \p pos is advanced behind the name.
734  * @return The Index of the named column.
735  */
736 static int LPFreadColName(char*& pos, NameSet* colnames, LPColSetBase<Real>& colset,
737  const LPColBase<Real>* emptycol, SPxOut* spxout)
738 {
739  assert(LPFisColName(pos));
740  assert(colnames != 0);
741 
742  char name[LPF_MAX_LINE_LEN];
743  const char* s = pos;
744  int i;
745  int colidx;
746 
747  // These are the characters that are not allowed in a column name.
748  while((strchr("+-.<>= ", *s) == 0) && (*s != '\0'))
749  s++;
750 
751  for(i = 0; pos != s; i++, pos++)
752  name[i] = *pos;
753 
754  name[i] = '\0';
755 
756  if((colidx = colnames->number(name)) < 0)
757  {
758  // We only add the name if we got an empty column.
759  if(emptycol == 0)
760  MSG_WARNING((*spxout), (*spxout) << "WLPFRD02 Unknown variable \"" << name << "\" ";)
761  else
762  {
763  colidx = colnames->num();
764  colnames->add(name);
765  colset.add(*emptycol);
766  }
767  }
768 
769  MSG_DEBUG(std::cout << "DLPFRD03 LPFreadColName [" << name << "] = " << colidx << std::endl;)
770 
771  if(LPFisSpace(*pos))
772  pos++;
773 
774  return colidx;
775 }
776 
777 
778 
779 /// Read the next <,>,=,==,<=,=<,>=,=> and advance \p pos.
780 static int LPFreadSense(char*& pos)
781 {
782  assert(LPFisSense(pos));
783 
784  int sense = *pos++;
785 
786  if((*pos == '<') || (*pos == '>'))
787  sense = *pos++;
788  else if(*pos == '=')
789  pos++;
790 
791  MSG_DEBUG(std::cout << "DLPFRD04 LPFreadSense = " << static_cast<char>(sense) << std::endl;)
792 
793  if(LPFisSpace(*pos))
794  pos++;
795 
796  return sense;
797 }
798 
799 
800 
801 /// Is the \p keyword present in \p buf ? If yes, advance \p pos.
802 /** \p keyword should be lower case. It can contain optional sections which are enclosed in '[' ']' like "min[imize]".
803  */
804 static bool LPFhasKeyword(char*& pos, const char* keyword)
805 {
806  int i;
807  int k;
808 
809  assert(keyword != 0);
810 
811  for(i = 0, k = 0; keyword[i] != '\0'; i++, k++)
812  {
813  if(keyword[i] == '[')
814  {
815  i++;
816 
817  // Here we assumed that we have a ']' for the '['.
818  while((tolower(pos[k]) == keyword[i]) && (pos[k] != '\0'))
819  {
820  k++;
821  i++;
822  }
823 
824  while(keyword[i] != ']')
825  i++;
826 
827  --k;
828  }
829  else
830  {
831  if(keyword[i] != tolower(pos[k]))
832  break;
833  }
834  }
835 
836  // we have to be at the end of the keyword and the word found on the line also has to end here. Attention: The
837  // LPFisSense is a kludge to allow LPFhasKeyword also to process Inf[inity] keywords in the bounds section.
838  if(keyword[i] == '\0' && (pos[k] == '\0' || LPFisSpace(pos[k]) || LPFisSense(&pos[k])))
839  {
840  pos += k;
841 
842  MSG_DEBUG(std::cout << "DLPFRD05 LPFhasKeyword: " << keyword << std::endl;)
843 
844  return true;
845  }
846 
847  return false;
848 }
849 
850 
851 
852 /// If \p buf start with "name:" store the name in \p rownames and advance \p pos.
853 static bool LPFhasRowName(char*& pos, NameSet* rownames)
854 {
855  const char* s = strchr(pos, ':');
856 
857  if(s == 0)
858  return false;
859 
860  int dcolpos = int(s - pos);
861 
862  int end;
863  int srt;
864 
865  // skip spaces between name and ":"
866  for(end = dcolpos - 1; end >= 0; end--)
867  if(pos[end] != ' ')
868  break;
869 
870  // are there only spaces in front of the ":" ?
871  if(end < 0)
872  {
873  pos = &(pos[dcolpos + 1]);
874  return false;
875  }
876 
877  // skip spaces in front of name
878  for(srt = end - 1; srt >= 0; srt--)
879  if(pos[srt] == ' ')
880  break;
881 
882  // go back to the non-space character
883  srt++;
884 
885  assert(srt <= end && pos[srt] != ' ');
886 
887  char name[LPF_MAX_LINE_LEN];
888  int i;
889  int k = 0;
890 
891  for(i = srt; i <= end; i++)
892  name[k++] = pos[i];
893 
894  name[k] = '\0';
895 
896  if(rownames != 0)
897  rownames->add(name);
898 
899  pos = &(pos[dcolpos + 1]);
900 
901  return true;
902 }
903 
904 
905 
906 static Real LPFreadInfinity(char*& pos)
907 {
908  assert(LPFisInfinity(pos));
909 
910  Real sense = (*pos == '-') ? -1.0 : 1.0;
911 
912  (void) LPFhasKeyword(++pos, "inf[inity]");
913 
914  return sense * infinity;
915 }
916 
917 
918 
919 /// Read LP in "CPLEX LP File Format".
920 /** The specification is taken from the ILOG CPLEX 7.0 Reference Manual, Appendix E, Page 527.
921  *
922  * This routine should read (most?) valid LP format files. What it will not do, is find all cases where a file is ill
923  * formed. If this happens it may complain and read nothing or read "something".
924  *
925  * Problem: A line ending in '+' or '-' followed by a line starting with a number, will be regarded as an error.
926  *
927  * The reader will accept the keyword INT[egers] as a synonym for GEN[erals] which is an undocumented feature in CPLEX.
928  *
929  * A difference to the CPLEX reader, is that no name for the objective row is required.
930  *
931  * The manual says the maximum allowed line length is 255 characters, but CPLEX does not complain if the lines are
932  * longer.
933  *
934  * @return true if the file was read correctly
935  */
936 template <>
938  std::istream& p_input, ///< input stream.
939  NameSet* p_rnames, ///< row names.
940  NameSet* p_cnames, ///< column names.
941  DIdxSet* p_intvars) ///< integer variables.
942 {
943  enum
944  {
945  START, OBJECTIVE, CONSTRAINTS, BOUNDS, INTEGERS, BINARIES
946  } section = START;
947 
948  NameSet* rnames; ///< row names.
949  NameSet* cnames; ///< column names.
950 
951  LPColSetBase<Real> cset; ///< the set of columns read.
952  LPRowSetBase<Real> rset; ///< the set of rows read.
953  LPColBase<Real> emptycol; ///< reusable empty column.
954  LPRowBase<Real> row; ///< last assembled row.
955  DSVectorBase<Real> vec; ///< last assembled vector (from row).
956 
957  Real val = 1.0;
958  int colidx;
959  int sense = 0;
960 
961  char buf[LPF_MAX_LINE_LEN];
962  char tmp[LPF_MAX_LINE_LEN];
963  char line[LPF_MAX_LINE_LEN];
964  int lineno = 0;
965  bool unnamed = true;
966  bool finished = false;
967  bool other;
968  bool have_value = true;
969  int i;
970  int k;
971  char* s;
972  char* pos;
973  char* pos_old = 0;
974 
975  if(p_cnames)
976  cnames = p_cnames;
977  else
978  {
979  cnames = 0;
980  spx_alloc(cnames);
981  cnames = new(cnames) NameSet();
982  }
983 
984  cnames->clear();
985 
986  if(p_rnames)
987  rnames = p_rnames;
988  else
989  {
990  try
991  {
992  rnames = 0;
993  spx_alloc(rnames);
994  rnames = new(rnames) NameSet();
995  }
996  catch(const SPxMemoryException& x)
997  {
998  if(!p_cnames)
999  {
1000  cnames->~NameSet();
1001  spx_free(cnames);
1002  }
1003 
1004  throw x;
1005  }
1006  }
1007 
1008  rnames->clear();
1009 
1010  SPxLPBase<Real>::clear(); // clear the LP.
1011 
1012  //--------------------------------------------------------------------------
1013  //--- Main Loop
1014  //--------------------------------------------------------------------------
1015  for(;;)
1016  {
1017  // 0. Read a line from the file.
1018  if(!p_input.getline(buf, sizeof(buf)))
1019  {
1020  if(strlen(buf) == LPF_MAX_LINE_LEN - 1)
1021  {
1022  MSG_ERROR(std::cerr << "ELPFRD06 Line exceeds " << LPF_MAX_LINE_LEN - 2
1023  << " characters" << std::endl;)
1024  }
1025  else
1026  {
1027  MSG_ERROR(std::cerr << "ELPFRD07 No 'End' marker found" << std::endl;)
1028  finished = true;
1029  }
1030 
1031  break;
1032  }
1033 
1034  lineno++;
1035  i = 0;
1036  pos = buf;
1037 
1038  MSG_DEBUG(std::cout << "DLPFRD08 Reading line " << lineno
1039  << " (pos=" << pos << ")" << std::endl;)
1040 
1041  // 1. Remove comments.
1042  if(0 != (s = strchr(buf, '\\')))
1043  * s = '\0';
1044 
1045  // 2. Look for keywords.
1046  if(section == START)
1047  {
1048  if(LPFhasKeyword(pos, "max[imize]"))
1049  {
1050  changeSense(SPxLPBase<Real>::MAXIMIZE);
1051  section = OBJECTIVE;
1052  }
1053  else if(LPFhasKeyword(pos, "min[imize]"))
1054  {
1055  changeSense(SPxLPBase<Real>::MINIMIZE);
1056  section = OBJECTIVE;
1057  }
1058  }
1059  else if(section == OBJECTIVE)
1060  {
1061  if(LPFhasKeyword(pos, "s[ubject][ ]t[o]")
1062  || LPFhasKeyword(pos, "s[uch][ ]t[hat]")
1063  || LPFhasKeyword(pos, "s[.][ ]t[.]")
1064  || LPFhasKeyword(pos, "lazy con[straints]"))
1065  {
1066  // store objective vector
1067  for(int j = vec.size() - 1; j >= 0; --j)
1068  cset.maxObj_w(vec.index(j)) = vec.value(j);
1069 
1070  // multiplication with -1 for minimization is done below
1071  vec.clear();
1072  have_value = true;
1073  val = 1.0;
1074  section = CONSTRAINTS;
1075  }
1076  }
1077  else if(section == CONSTRAINTS &&
1078  (LPFhasKeyword(pos, "s[ubject][ ]t[o]")
1079  || LPFhasKeyword(pos, "s[uch][ ]t[hat]")
1080  || LPFhasKeyword(pos, "s[.][ ]t[.]")))
1081  {
1082  have_value = true;
1083  val = 1.0;
1084  }
1085  else
1086  {
1087  if(LPFhasKeyword(pos, "lazy con[straints]"))
1088  ;
1089  else if(LPFhasKeyword(pos, "bound[s]"))
1090  section = BOUNDS;
1091  else if(LPFhasKeyword(pos, "bin[ary]"))
1092  section = BINARIES;
1093  else if(LPFhasKeyword(pos, "bin[aries]"))
1094  section = BINARIES;
1095  else if(LPFhasKeyword(pos, "gen[erals]"))
1096  section = INTEGERS;
1097  else if(LPFhasKeyword(pos, "int[egers]")) // this is undocumented
1098  section = INTEGERS;
1099  else if(LPFhasKeyword(pos, "end"))
1100  {
1101  finished = true;
1102  break;
1103  }
1104  else if(LPFhasKeyword(pos, "s[ubject][ ]t[o]") // second time
1105  || LPFhasKeyword(pos, "s[uch][ ]t[hat]")
1106  || LPFhasKeyword(pos, "s[.][ ]t[.]")
1107  || LPFhasKeyword(pos, "lazy con[straints]"))
1108  {
1109  // In principle this has to checked for all keywords above,
1110  // otherwise we just ignore any half finished constraint
1111  if(have_value)
1112  goto syntax_error;
1113 
1114  have_value = true;
1115  val = 1.0;
1116  }
1117  }
1118 
1119  // 3a. Look for row names in objective and drop it.
1120  if(section == OBJECTIVE)
1121  LPFhasRowName(pos, 0);
1122 
1123  // 3b. Look for row name in constraint and store it.
1124  if(section == CONSTRAINTS)
1125  if(LPFhasRowName(pos, rnames))
1126  unnamed = false;
1127 
1128  // 4a. Remove initial spaces.
1129  while(LPFisSpace(pos[i]))
1130  i++;
1131 
1132  // 4b. remove spaces if they do not appear before the name of a vaiable.
1133  for(k = 0; pos[i] != '\0'; i++)
1134  if(!LPFisSpace(pos[i]) || LPFisColName(&pos[i + 1]))
1135  tmp[k++] = pos[i];
1136 
1137  tmp[k] = '\0';
1138 
1139  // 5. Is this an empty line ?
1140  if(tmp[0] == '\0')
1141  continue;
1142 
1143  // 6. Collapse sequences of '+' and '-'. e.g ++---+ => -
1144  for(i = 0, k = 0; tmp[i] != '\0'; i++)
1145  {
1146  while(((tmp[i] == '+') || (tmp[i] == '-')) && ((tmp[i + 1] == '+') || (tmp[i + 1] == '-')))
1147  {
1148  if(tmp[i++] == '-')
1149  tmp[i] = (tmp[i] == '-') ? '+' : '-';
1150  }
1151 
1152  line[k++] = tmp[i];
1153  }
1154 
1155  line[k] = '\0';
1156 
1157  //-----------------------------------------------------------------------
1158  //--- Line processing loop
1159  //-----------------------------------------------------------------------
1160  pos = line;
1161 
1162  MSG_DEBUG(std::cout << "DLPFRD09 pos=" << pos << std::endl;)
1163 
1164  // 7. We have something left to process.
1165  while((pos != 0) && (*pos != '\0'))
1166  {
1167  // remember our position, so we are sure we make progress.
1168  pos_old = pos;
1169 
1170  // now process the sections
1171  switch(section)
1172  {
1173  case OBJECTIVE:
1174  if(LPFisValue(pos))
1175  {
1176  Real pre_sign = 1.0;
1177 
1178  /* Already having here a value could only result from being the first number in a constraint, or a sign
1179  * '+' or '-' as last token on the previous line.
1180  */
1181  if(have_value)
1182  {
1183  if(NE(spxAbs(val), 1.0))
1184  goto syntax_error;
1185 
1186  if(EQ(val, -1.0))
1187  pre_sign = val;
1188  }
1189 
1190  /* non-finite coefficients are not allowed in the objective */
1191  if(LPFisInfinity(pos))
1192  goto syntax_error;
1193 
1194  have_value = true;
1195  val = LPFreadValue(pos, spxout) * pre_sign;
1196  }
1197 
1198  if(*pos == '\0')
1199  continue;
1200 
1201  if(!have_value || !LPFisColName(pos))
1202  goto syntax_error;
1203 
1204  have_value = false;
1205  colidx = LPFreadColName(pos, cnames, cset, &emptycol, spxout);
1206  vec.add(colidx, val);
1207  break;
1208 
1209  case CONSTRAINTS:
1210  if(LPFisValue(pos))
1211  {
1212  Real pre_sign = 1.0;
1213 
1214  /* Already having here a value could only result from being the first number in a constraint, or a sign
1215  * '+' or '-' as last token on the previous line.
1216  */
1217  if(have_value)
1218  {
1219  if(NE(spxAbs(val), 1.0))
1220  goto syntax_error;
1221 
1222  if(EQ(val, -1.0))
1223  pre_sign = val;
1224  }
1225 
1226  if(LPFisInfinity(pos))
1227  {
1228  /* non-finite coefficients are not allowed */
1229  if(sense == 0)
1230  goto syntax_error;
1231 
1232  val = LPFreadInfinity(pos) * pre_sign;
1233  }
1234  else
1235  val = LPFreadValue(pos, spxout) * pre_sign;
1236 
1237  have_value = true;
1238 
1239  if(sense != 0)
1240  {
1241  if(sense == '<')
1242  {
1243  row.setLhs(-infinity);
1244  row.setRhs(val);
1245  }
1246  else if(sense == '>')
1247  {
1248  row.setLhs(val);
1249  row.setRhs(infinity);
1250  }
1251  else
1252  {
1253  assert(sense == '=');
1254 
1255  row.setLhs(val);
1256  row.setRhs(val);
1257  }
1258 
1259  row.setRowVector(vec);
1260  rset.add(row);
1261  vec.clear();
1262 
1263  if(!unnamed)
1264  unnamed = true;
1265  else
1266  {
1267  char name[16];
1268  spxSnprintf(name, 16, "C%d", rset.num());
1269  rnames->add(name);
1270  }
1271 
1272  have_value = true;
1273  val = 1.0;
1274  sense = 0;
1275  pos = 0;
1276  // next line
1277  continue;
1278  }
1279  }
1280 
1281  if(*pos == '\0')
1282  continue;
1283 
1284  if(have_value)
1285  {
1286  if(LPFisColName(pos))
1287  {
1288  colidx = LPFreadColName(pos, cnames, cset, &emptycol, spxout);
1289 
1290  if(val != 0.0)
1291  {
1292  // Do we have this index already in the row?
1293  int n = vec.pos(colidx);
1294 
1295  // if not, add it
1296  if(n < 0)
1297  vec.add(colidx, val);
1298  // if yes, add them up and remove the element if it amounts to zero
1299  else
1300  {
1301  assert(vec.index(n) == colidx);
1302 
1303  val += vec.value(n);
1304 
1305  if(val == 0.0)
1306  vec.remove(n);
1307  else
1308  vec.value(n) = val;
1309 
1310  assert(cnames->has(colidx));
1311 
1312  MSG_WARNING((*spxout), (*spxout) << "WLPFRD10 Duplicate index "
1313  << (*cnames)[colidx]
1314  << " in line " << lineno
1315  << std::endl;)
1316  }
1317  }
1318 
1319  have_value = false;
1320  }
1321  else
1322  {
1323  // We have a row like c1: <= 5 with no variables. We can not handle 10 <= 5; issue a syntax error.
1324  if(val != 1.0)
1325  goto syntax_error;
1326 
1327  // If the next thing is not the sense we give up also.
1328  if(!LPFisSense(pos))
1329  goto syntax_error;
1330 
1331  have_value = false;
1332  }
1333  }
1334 
1335  assert(!have_value);
1336 
1337  if(LPFisSense(pos))
1338  sense = LPFreadSense(pos);
1339 
1340  break;
1341 
1342  case BOUNDS:
1343  other = false;
1344  sense = 0;
1345 
1346  if(LPFisValue(pos))
1347  {
1348  val = LPFisInfinity(pos) ? LPFreadInfinity(pos) : LPFreadValue(pos, spxout);
1349 
1350  if(!LPFisSense(pos))
1351  goto syntax_error;
1352 
1353  sense = LPFreadSense(pos);
1354  other = true;
1355  }
1356 
1357  if(!LPFisColName(pos))
1358  goto syntax_error;
1359 
1360  if((colidx = LPFreadColName(pos, cnames, cset, 0, spxout)) < 0)
1361  {
1362  MSG_WARNING((*spxout), (*spxout) << "WLPFRD11 in Bounds section line "
1363  << lineno << " ignored" << std::endl;)
1364  *pos = '\0';
1365  continue;
1366  }
1367 
1368  if(sense)
1369  {
1370  if(sense == '<')
1371  cset.lower_w(colidx) = val;
1372  else if(sense == '>')
1373  cset.upper_w(colidx) = val;
1374  else
1375  {
1376  assert(sense == '=');
1377  cset.lower_w(colidx) = val;
1378  cset.upper_w(colidx) = val;
1379  }
1380  }
1381 
1382  if(LPFisFree(pos))
1383  {
1384  cset.lower_w(colidx) = -infinity;
1385  cset.upper_w(colidx) = infinity;
1386  other = true;
1387  pos += 4; // set position after the word "free"
1388  }
1389  else if(LPFisSense(pos))
1390  {
1391  sense = LPFreadSense(pos);
1392  other = true;
1393 
1394  if(!LPFisValue(pos))
1395  goto syntax_error;
1396 
1397  val = LPFisInfinity(pos) ? LPFreadInfinity(pos) : LPFreadValue(pos, spxout);
1398 
1399  if(sense == '<')
1400  cset.upper_w(colidx) = val;
1401  else if(sense == '>')
1402  cset.lower_w(colidx) = val;
1403  else
1404  {
1405  assert(sense == '=');
1406  cset.lower_w(colidx) = val;
1407  cset.upper_w(colidx) = val;
1408  }
1409  }
1410 
1411  /* Do we have only a single column name in the input line? We could ignore this savely, but it is probably
1412  * a sign of some other error.
1413  */
1414  if(!other)
1415  goto syntax_error;
1416 
1417  break;
1418 
1419  case BINARIES:
1420  case INTEGERS:
1421  if((colidx = LPFreadColName(pos, cnames, cset, 0, spxout)) < 0)
1422  {
1423  MSG_WARNING((*spxout), (*spxout) << "WLPFRD12 in Binary/General section line " << lineno <<
1424  " ignored" << std::endl;)
1425  }
1426  else
1427  {
1428  if(section == BINARIES)
1429  {
1430  if(cset.lower(colidx) < 0.0)
1431  {
1432  cset.lower_w(colidx) = 0.0;
1433  }
1434 
1435  if(cset.upper(colidx) > 1.0)
1436  {
1437  cset.upper_w(colidx) = 1.0;
1438  }
1439  }
1440 
1441  if(p_intvars != 0)
1442  p_intvars->addIdx(colidx);
1443  }
1444 
1445  break;
1446 
1447  case START:
1448  MSG_ERROR(std::cerr << "ELPFRD13 This seems to be no LP format file" << std::endl;)
1449  goto syntax_error;
1450 
1451  default:
1452  throw SPxInternalCodeException("XLPFRD01 This should never happen.");
1453  }
1454 
1455  if(pos == pos_old)
1456  goto syntax_error;
1457  }
1458  }
1459 
1460  assert(isConsistent());
1461 
1462  addCols(cset);
1463  assert(isConsistent());
1464 
1465  addRows(rset);
1466  assert(isConsistent());
1467 
1468 syntax_error:
1469 
1470  if(finished)
1471  {
1472  MSG_INFO2((*spxout), (*spxout) << "Finished reading " << lineno << " lines" << std::endl;)
1473  }
1474  else
1475  MSG_ERROR(std::cerr << "ELPFRD15 Syntax error in line " << lineno << std::endl;)
1476 
1477  if(p_cnames == 0)
1478  spx_free(cnames);
1479 
1480  if(p_rnames == 0)
1481  spx_free(rnames);
1482 
1483  return finished;
1484 }
1485 
1486 
1487 
1488 // ---------------------------------------------------------------------------------------------------------------------
1489 // Specialization for reading MPS format
1490 // ---------------------------------------------------------------------------------------------------------------------
1491 
1492 /// Process NAME section.
1493 static void MPSreadName(MPSInput& mps, SPxOut* spxout)
1494 {
1495  do
1496  {
1497  // This has to be the Line with the NAME section.
1498  if(!mps.readLine() || (mps.field0() == 0) || strcmp(mps.field0(), "NAME"))
1499  break;
1500 
1501  // Sometimes the name is omitted.
1502  mps.setProbName((mps.field1() == 0) ? "_MPS_" : mps.field1());
1503 
1504  MSG_INFO2((*spxout), (*spxout) << "IMPSRD01 Problem name : " << mps.probName() << std::endl;)
1505 
1506  // This has to be a new section
1507  if(!mps.readLine() || (mps.field0() == 0))
1508  break;
1509 
1510  if(!strcmp(mps.field0(), "ROWS"))
1512  else if(!strncmp(mps.field0(), "OBJSEN", 6))
1513  mps.setSection(MPSInput::OBJSEN);
1514  else if(!strcmp(mps.field0(), "OBJNAME"))
1515  mps.setSection(MPSInput::OBJNAME);
1516  else
1517  break;
1518 
1519  return;
1520  }
1521  while(false);
1522 
1523  mps.syntaxError();
1524 }
1525 
1526 
1527 
1528 /// Process OBJSEN section. This Section is an ILOG extension.
1529 static void MPSreadObjsen(MPSInput& mps)
1530 {
1531  do
1532  {
1533  // This has to be the Line with MIN or MAX.
1534  if(!mps.readLine() || (mps.field1() == 0))
1535  break;
1536 
1537  if(!strcmp(mps.field1(), "MIN"))
1538  mps.setObjSense(MPSInput::MINIMIZE);
1539  else if(!strcmp(mps.field1(), "MAX"))
1540  mps.setObjSense(MPSInput::MAXIMIZE);
1541  else
1542  break;
1543 
1544  // Look for ROWS or OBJNAME Section
1545  if(!mps.readLine() || (mps.field0() == 0))
1546  break;
1547 
1548  if(!strcmp(mps.field0(), "ROWS"))
1550  else if(!strcmp(mps.field0(), "OBJNAME"))
1551  mps.setSection(MPSInput::OBJNAME);
1552  else
1553  break;
1554 
1555  return;
1556  }
1557  while(false);
1558 
1559  mps.syntaxError();
1560 }
1561 
1562 
1563 
1564 /// Process OBJNAME section. This Section is an ILOG extension.
1565 static void MPSreadObjname(MPSInput& mps)
1566 {
1567  do
1568  {
1569  // This has to be the Line with the name.
1570  if(!mps.readLine() || (mps.field1() == 0))
1571  break;
1572 
1573  mps.setObjName(mps.field1());
1574 
1575  // Look for ROWS Section
1576  if(!mps.readLine() || (mps.field0() == 0))
1577  break;
1578 
1579  if(strcmp(mps.field0(), "ROWS"))
1580  break;
1581 
1583 
1584  return;
1585  }
1586  while(false);
1587 
1588  mps.syntaxError();
1589 }
1590 
1591 
1592 
1593 /// Process ROWS section.
1594 static void MPSreadRows(MPSInput& mps, LPRowSetBase<Real>& rset, NameSet& rnames, SPxOut* spxout)
1595 {
1596  LPRowBase<Real> row;
1597 
1598  while(mps.readLine())
1599  {
1600  if(mps.field0() != 0)
1601  {
1602  MSG_INFO2((*spxout), (*spxout) << "IMPSRD02 Objective name : " << mps.objName() << std::endl;)
1603 
1604  if(strcmp(mps.field0(), "COLUMNS"))
1605  break;
1606 
1607  mps.setSection(MPSInput::COLUMNS);
1608 
1609  return;
1610  }
1611 
1612  if((mps.field1() == 0) || (mps.field2() == 0))
1613  break;
1614 
1615  if(*mps.field1() == 'N')
1616  {
1617  if(*mps.objName() == '\0')
1618  mps.setObjName(mps.field2());
1619  }
1620  else
1621  {
1622  if(rnames.has(mps.field2()))
1623  break;
1624 
1625  rnames.add(mps.field2());
1626 
1627  switch(*mps.field1())
1628  {
1629  case 'G':
1630  row.setLhs(0.0);
1631  row.setRhs(infinity);
1632  break;
1633 
1634  case 'E':
1635  row.setLhs(0.0);
1636  row.setRhs(0.0);
1637  break;
1638 
1639  case 'L':
1640  row.setLhs(-infinity);
1641  row.setRhs(0.0);
1642  break;
1643 
1644  default:
1645  mps.syntaxError();
1646  return;
1647  }
1648 
1649  rset.add(row);
1650  }
1651 
1652  assert((*mps.field1() == 'N') || (rnames.number(mps.field2()) == rset.num() - 1));
1653  }
1654 
1655  mps.syntaxError();
1656 }
1657 
1658 
1659 
1660 /// Process COLUMNS section.
1661 static void MPSreadCols(MPSInput& mps, const LPRowSetBase<Real>& rset, const NameSet& rnames,
1662  LPColSetBase<Real>& cset, NameSet& cnames, DIdxSet* intvars)
1663 {
1664  Real val;
1665  int idx;
1666  char colname[MPSInput::MAX_LINE_LEN] = { '\0' };
1667  LPColBase<Real> col(rset.num());
1668  DSVectorBase<Real> vec;
1669 
1670  col.setObj(0.0);
1671  vec.clear();
1672 
1673  while(mps.readLine())
1674  {
1675  if(mps.field0() != 0)
1676  {
1677  if(strcmp(mps.field0(), "RHS"))
1678  break;
1679 
1680  if(colname[0] != '\0')
1681  {
1682  col.setColVector(vec);
1683  cset.add(col);
1684  }
1685 
1686  mps.setSection(MPSInput::RHS);
1687 
1688  return;
1689  }
1690 
1691  if((mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0))
1692  break;
1693 
1694  // new column?
1695  if(strcmp(colname, mps.field1()))
1696  {
1697  // first column?
1698  if(colname[0] != '\0')
1699  {
1700  col.setColVector(vec);
1701  cset.add(col);
1702  }
1703 
1704  // save copy of string (make sure string ends with \0)
1705  spxSnprintf(colname, MPSInput::MAX_LINE_LEN - 1, "%s", mps.field1());
1706  colname[MPSInput::MAX_LINE_LEN - 1] = '\0';
1707 
1708  int ncnames = cnames.size();
1709  cnames.add(colname);
1710 
1711  // check whether the new name is unique wrt previous column names
1712  if(cnames.size() <= ncnames)
1713  {
1714  MSG_ERROR(std::cerr << "ERROR in COLUMNS: duplicate column name or not column-wise ordering" <<
1715  std::endl;)
1716  break;
1717  }
1718 
1719  vec.clear();
1720  col.setObj(0.0);
1721  col.setLower(0.0);
1722  col.setUpper(infinity);
1723 
1724  if(mps.isInteger())
1725  {
1726  assert(cnames.number(colname) == cset.num());
1727 
1728  if(intvars != 0)
1729  intvars->addIdx(cnames.number(colname));
1730 
1731  // for Integer variable the default bounds are 0/1
1732  col.setUpper(1.0);
1733  }
1734  }
1735 
1736  val = atof(mps.field3());
1737 
1738  if(!strcmp(mps.field2(), mps.objName()))
1739  col.setObj(val);
1740  else
1741  {
1742  if((idx = rnames.number(mps.field2())) < 0)
1743  mps.entryIgnored("Column", mps.field1(), "row", mps.field2());
1744  else if(val != 0.0)
1745  vec.add(idx, val);
1746  }
1747 
1748  if(mps.field5() != 0)
1749  {
1750  assert(mps.field4() != 0);
1751 
1752  val = atof(mps.field5());
1753 
1754  if(!strcmp(mps.field4(), mps.objName()))
1755  col.setObj(val);
1756  else
1757  {
1758  if((idx = rnames.number(mps.field4())) < 0)
1759  mps.entryIgnored("Column", mps.field1(), "row", mps.field4());
1760  else if(val != 0.0)
1761  vec.add(idx, val);
1762  }
1763  }
1764  }
1765 
1766  mps.syntaxError();
1767 }
1768 
1769 
1770 
1771 /// Process RHS section.
1772 static void MPSreadRhs(MPSInput& mps, LPRowSetBase<Real>& rset, const NameSet& rnames,
1773  SPxOut* spxout)
1774 {
1775  char rhsname[MPSInput::MAX_LINE_LEN] = { '\0' };
1776  char addname[MPSInput::MAX_LINE_LEN] = { '\0' };
1777  int idx;
1778  Real val;
1779 
1780  while(mps.readLine())
1781  {
1782  if(mps.field0() != 0)
1783  {
1784  MSG_INFO2((*spxout), (*spxout) << "IMPSRD03 RHS name : " << rhsname << std::endl;);
1785 
1786  if(!strcmp(mps.field0(), "RANGES"))
1787  mps.setSection(MPSInput::RANGES);
1788  else if(!strcmp(mps.field0(), "BOUNDS"))
1789  mps.setSection(MPSInput::BOUNDS);
1790  else if(!strcmp(mps.field0(), "ENDATA"))
1791  mps.setSection(MPSInput::ENDATA);
1792  else
1793  break;
1794 
1795  return;
1796  }
1797 
1798  if(((mps.field2() != 0) && (mps.field3() == 0)) || ((mps.field4() != 0) && (mps.field5() == 0)))
1799  mps.insertName("_RHS_");
1800 
1801  if((mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0))
1802  break;
1803 
1804  if(*rhsname == '\0')
1805  spxSnprintf(rhsname, MPSInput::MAX_LINE_LEN, "%s", mps.field1());
1806 
1807  if(strcmp(rhsname, mps.field1()))
1808  {
1809  if(strcmp(addname, mps.field1()))
1810  {
1811  assert(strlen(mps.field1()) < MPSInput::MAX_LINE_LEN);
1812  spxSnprintf(addname, MPSInput::MAX_LINE_LEN, "%s", mps.field1());
1813  MSG_INFO3((*spxout), (*spxout) << "IMPSRD07 RHS ignored : " << addname << std::endl);
1814  }
1815  }
1816  else
1817  {
1818  if((idx = rnames.number(mps.field2())) < 0)
1819  mps.entryIgnored("RHS", mps.field1(), "row", mps.field2());
1820  else
1821  {
1822  val = atof(mps.field3());
1823 
1824  // LE or EQ
1825  if(rset.rhs(idx) < infinity)
1826  rset.rhs_w(idx) = val;
1827 
1828  // GE or EQ
1829  if(rset.lhs(idx) > -infinity)
1830  rset.lhs_w(idx) = val;
1831  }
1832 
1833  if(mps.field5() != 0)
1834  {
1835  if((idx = rnames.number(mps.field4())) < 0)
1836  mps.entryIgnored("RHS", mps.field1(), "row", mps.field4());
1837  else
1838  {
1839  val = atof(mps.field5());
1840 
1841  // LE or EQ
1842  if(rset.rhs(idx) < infinity)
1843  rset.rhs_w(idx) = val;
1844 
1845  // GE or EQ
1846  if(rset.lhs(idx) > -infinity)
1847  rset.lhs_w(idx) = val;
1848  }
1849  }
1850  }
1851  }
1852 
1853  mps.syntaxError();
1854 }
1855 
1856 
1857 
1858 /// Process RANGES section.
1859 static void MPSreadRanges(MPSInput& mps, LPRowSetBase<Real>& rset, const NameSet& rnames,
1860  SPxOut* spxout)
1861 {
1862  char rngname[MPSInput::MAX_LINE_LEN] = { '\0' };
1863  int idx;
1864  Real val;
1865 
1866  while(mps.readLine())
1867  {
1868  if(mps.field0() != 0)
1869  {
1870  MSG_INFO2((*spxout), (*spxout) << "IMPSRD04 Range name : " << rngname << std::endl;);
1871 
1872  if(!strcmp(mps.field0(), "BOUNDS"))
1873  mps.setSection(MPSInput::BOUNDS);
1874  else if(!strcmp(mps.field0(), "ENDATA"))
1875  mps.setSection(MPSInput::ENDATA);
1876  else
1877  break;
1878 
1879  return;
1880  }
1881 
1882  if(((mps.field2() != 0) && (mps.field3() == 0)) || ((mps.field4() != 0) && (mps.field5() == 0)))
1883  mps.insertName("_RNG_");
1884 
1885  if((mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0))
1886  break;
1887 
1888  if(*rngname == '\0')
1889  {
1890  assert(strlen(mps.field1()) < MPSInput::MAX_LINE_LEN);
1891  spxSnprintf(rngname, MPSInput::MAX_LINE_LEN, "%s", mps.field1());
1892  }
1893 
1894  /* The rules are:
1895  * Row Sign LHS RHS
1896  * ----------------------------------------
1897  * G +/- rhs rhs + |range|
1898  * L +/- rhs - |range| rhs
1899  * E + rhs rhs + range
1900  * E - rhs + range rhs
1901  * ----------------------------------------
1902  */
1903  if(!strcmp(rngname, mps.field1()))
1904  {
1905  if((idx = rnames.number(mps.field2())) < 0)
1906  mps.entryIgnored("Range", mps.field1(), "row", mps.field2());
1907  else
1908  {
1909  val = atof(mps.field3());
1910 
1911  // EQ
1912  if((rset.lhs(idx) > -infinity) && (rset.rhs_w(idx) < infinity))
1913  {
1914  assert(rset.lhs(idx) == rset.rhs(idx));
1915 
1916  if(val >= 0)
1917  rset.rhs_w(idx) += val;
1918  else
1919  rset.lhs_w(idx) += val;
1920  }
1921  else
1922  {
1923  // GE
1924  if(rset.lhs(idx) > -infinity)
1925  rset.rhs_w(idx) = rset.lhs(idx) + spxAbs(val);
1926  // LE
1927  else
1928  rset.lhs_w(idx) = rset.rhs(idx) - spxAbs(val);
1929  }
1930  }
1931 
1932  if(mps.field5() != 0)
1933  {
1934  if((idx = rnames.number(mps.field4())) < 0)
1935  mps.entryIgnored("Range", mps.field1(), "row", mps.field4());
1936  else
1937  {
1938  val = atof(mps.field5());
1939 
1940  // EQ
1941  if((rset.lhs(idx) > -infinity) && (rset.rhs(idx) < infinity))
1942  {
1943  assert(rset.lhs(idx) == rset.rhs(idx));
1944 
1945  if(val >= 0)
1946  rset.rhs_w(idx) += val;
1947  else
1948  rset.lhs_w(idx) += val;
1949  }
1950  else
1951  {
1952  // GE
1953  if(rset.lhs(idx) > -infinity)
1954  rset.rhs_w(idx) = rset.lhs(idx) + spxAbs(val);
1955  // LE
1956  else
1957  rset.lhs_w(idx) = rset.rhs(idx) - spxAbs(val);
1958  }
1959  }
1960  }
1961  }
1962  }
1963 
1964  mps.syntaxError();
1965 }
1966 
1967 
1968 
1969 /// Process BOUNDS section.
1970 static void MPSreadBounds(MPSInput& mps, LPColSetBase<Real>& cset, const NameSet& cnames,
1971  DIdxSet* intvars, SPxOut* spxout)
1972 {
1973  DIdxSet oldbinvars;
1974  char bndname[MPSInput::MAX_LINE_LEN] = { '\0' };
1975  int idx;
1976  Real val;
1977 
1978  while(mps.readLine())
1979  {
1980  if(mps.field0() != 0)
1981  {
1982  MSG_INFO2((*spxout), (*spxout) << "IMPSRD05 Bound name : " << bndname << std::endl;)
1983 
1984  if(strcmp(mps.field0(), "ENDATA"))
1985  break;
1986 
1987  mps.setSection(MPSInput::ENDATA);
1988 
1989  return;
1990  }
1991 
1992  // Is the value field used ?
1993  if((!strcmp(mps.field1(), "LO"))
1994  || (!strcmp(mps.field1(), "UP"))
1995  || (!strcmp(mps.field1(), "FX"))
1996  || (!strcmp(mps.field1(), "LI"))
1997  || (!strcmp(mps.field1(), "UI")))
1998  {
1999  if((mps.field3() != 0) && (mps.field4() == 0))
2000  mps.insertName("_BND_", true);
2001  }
2002  else
2003  {
2004  if((mps.field2() != 0) && (mps.field3() == 0))
2005  mps.insertName("_BND_", true);
2006  }
2007 
2008  if((mps.field1() == 0) || (mps.field2() == 0) || (mps.field3() == 0))
2009  break;
2010 
2011  if(*bndname == '\0')
2012  {
2013  assert(strlen(mps.field2()) < MPSInput::MAX_LINE_LEN);
2014  spxSnprintf(bndname, MPSInput::MAX_LINE_LEN, "%s", mps.field2());
2015  }
2016 
2017  // Only read the first Bound in section
2018  if(!strcmp(bndname, mps.field2()))
2019  {
2020  if((idx = cnames.number(mps.field3())) < 0)
2021  mps.entryIgnored("column", mps.field3(), "bound", bndname);
2022  else
2023  {
2024  if(mps.field4() == 0)
2025  val = 0.0;
2026  else if(!strcmp(mps.field4(), "-Inf") || !strcmp(mps.field4(), "-inf"))
2027  val = -infinity;
2028  else if(!strcmp(mps.field4(), "Inf") || !strcmp(mps.field4(), "inf")
2029  || !strcmp(mps.field4(), "+Inf") || !strcmp(mps.field4(), "+inf"))
2030  val = infinity;
2031  else
2032  val = atof(mps.field4());
2033 
2034  // ILOG extension (Integer Bound)
2035  if(mps.field1()[1] == 'I')
2036  {
2037  if(intvars != 0)
2038  intvars->addIdx(idx);
2039 
2040  // if the variable has appeared in the MARKER section of the COLUMNS section then its default bounds were
2041  // set to 0,1; the first time it is declared integer we need to change to default bounds 0,infinity
2042  if(oldbinvars.pos(idx) < 0)
2043  {
2044  cset.upper_w(idx) = infinity;
2045  oldbinvars.addIdx(idx);
2046  }
2047  }
2048 
2049  switch(*mps.field1())
2050  {
2051  case 'L':
2052  cset.lower_w(idx) = val;
2053  break;
2054 
2055  case 'U':
2056  cset.upper_w(idx) = val;
2057  break;
2058 
2059  case 'F':
2060  if(mps.field1()[1] == 'X')
2061  {
2062  cset.lower_w(idx) = val;
2063  cset.upper_w(idx) = val;
2064  }
2065  else
2066  {
2067  cset.lower_w(idx) = -infinity;
2068  cset.upper_w(idx) = infinity;
2069  }
2070 
2071  break;
2072 
2073  case 'M':
2074  cset.lower_w(idx) = -infinity;
2075  break;
2076 
2077  case 'P':
2078  cset.upper_w(idx) = infinity;
2079  break;
2080 
2081  // Ilog extension (Binary)
2082  case 'B':
2083  cset.lower_w(idx) = 0.0;
2084  cset.upper_w(idx) = 1.0;
2085 
2086  if(intvars != 0)
2087  intvars->addIdx(idx);
2088 
2089  break;
2090 
2091  default:
2092  mps.syntaxError();
2093  return;
2094  }
2095  }
2096  }
2097  }
2098 
2099  mps.syntaxError();
2100 }
2101 
2102 
2103 
2104 /// Read LP in MPS File Format.
2105 /**
2106  * The specification is taken from the IBM Optimization Library Guide and Reference, online available at
2107  * http://www.software.ibm.com/sos/features/libuser.htm and from the ILOG CPLEX 7.0 Reference Manual, Appendix E, Page
2108  * 531.
2109  *
2110  * This routine should read all valid MPS format files. What it will not do, is find all cases where a file is ill
2111  * formed. If this happens it may complain and read nothing or read "something".
2112  *
2113  * @return true if the file was read correctly.
2114  */
2115 #define INIT_COLS 10000 ///< initialy allocated columns.
2116 #define INIT_NZOS 100000 ///< initialy allocated non zeros.
2117 template <>
2119  std::istream& p_input, ///< input stream.
2120  NameSet* p_rnames, ///< row names.
2121  NameSet* p_cnames, ///< column names.
2122  DIdxSet* p_intvars) ///< integer variables.
2123 {
2124  LPRowSetBase<Real>& rset = *this;
2125  LPColSetBase<Real>& cset = *this;
2126  NameSet* rnames;
2127  NameSet* cnames;
2128 
2129  if(p_cnames)
2130  cnames = p_cnames;
2131  else
2132  {
2133  cnames = 0;
2134  spx_alloc(cnames);
2135  cnames = new(cnames) NameSet();
2136  }
2137 
2138  cnames->clear();
2139 
2140  if(p_rnames)
2141  rnames = p_rnames;
2142  else
2143  {
2144  try
2145  {
2146  rnames = 0;
2147  spx_alloc(rnames);
2148  rnames = new(rnames) NameSet();
2149  }
2150  catch(const SPxMemoryException& x)
2151  {
2152  if(!p_cnames)
2153  {
2154  cnames->~NameSet();
2155  spx_free(cnames);
2156  }
2157 
2158  throw x;
2159  }
2160  }
2161 
2162  rnames->clear();
2163 
2164  SPxLPBase<Real>::clear(); // clear the LP.
2165 
2166  cset.memRemax(INIT_NZOS);
2167  cset.reMax(INIT_COLS);
2168 
2169  MPSInput mps(p_input);
2170 
2171  MPSreadName(mps, spxout);
2172 
2173  if(mps.section() == MPSInput::OBJSEN)
2174  MPSreadObjsen(mps);
2175 
2176  if(mps.section() == MPSInput::OBJNAME)
2177  MPSreadObjname(mps);
2178 
2179  if(mps.section() == MPSInput::ROWS)
2180  MPSreadRows(mps, rset, *rnames, spxout);
2181 
2182  addedRows(rset.num());
2183 
2184  if(mps.section() == MPSInput::COLUMNS)
2185  MPSreadCols(mps, rset, *rnames, cset, *cnames, p_intvars);
2186 
2187  if(mps.section() == MPSInput::RHS)
2188  MPSreadRhs(mps, rset, *rnames, spxout);
2189 
2190  if(mps.section() == MPSInput::RANGES)
2191  MPSreadRanges(mps, rset, *rnames, spxout);
2192 
2193  if(mps.section() == MPSInput::BOUNDS)
2194  MPSreadBounds(mps, cset, *cnames, p_intvars, spxout);
2195 
2196  if(mps.section() != MPSInput::ENDATA)
2197  mps.syntaxError();
2198 
2199  if(mps.hasError())
2200  clear();
2201  else
2202  {
2203  changeSense(mps.objSense() == MPSInput::MINIMIZE ? SPxLPBase<Real>::MINIMIZE :
2205 
2206  MSG_INFO2((*spxout), (*spxout) << "IMPSRD06 Objective sense: " << ((mps.objSense() ==
2207  MPSInput::MINIMIZE) ? "Minimize\n" : "Maximize\n"));
2208 
2209  added2Set(
2210  *(reinterpret_cast<SVSetBase<Real>*>(static_cast<LPRowSetBase<Real>*>(this))),
2211  *(reinterpret_cast<SVSetBase<Real>*>(static_cast<LPColSetBase<Real>*>(this))),
2212  cset.num());
2213  addedCols(cset.num());
2214 
2215  assert(isConsistent());
2216  }
2217 
2218  if(p_cnames == 0)
2219  {
2220  cnames->~NameSet();
2221  spx_free(cnames);
2222  }
2223 
2224  if(p_rnames == 0)
2225  {
2226  rnames->~NameSet();
2227  spx_free(rnames);
2228  }
2229 
2230  return !mps.hasError();
2231 }
2232 
2233 
2234 
2235 // ---------------------------------------------------------------------------------------------------------------------
2236 // Specialization for writing LP format
2237 // ---------------------------------------------------------------------------------------------------------------------
2238 
2239 // get the name of a row or construct one
2240 static const char* LPFgetRowName(
2241  const SPxLPBase<Real>& p_lp,
2242  int p_idx,
2243  const NameSet* p_rnames,
2244  char* p_buf,
2245  int p_num_written_rows
2246 )
2247 {
2248  assert(p_buf != 0);
2249  assert(p_idx >= 0);
2250  assert(p_idx < p_lp.nRows());
2251 
2252  if(p_rnames != 0)
2253  {
2254  DataKey key = p_lp.rId(p_idx);
2255 
2256  if(p_rnames->has(key))
2257  return (*p_rnames)[key];
2258  }
2259 
2260  spxSnprintf(p_buf, 16, "C%d", p_num_written_rows);
2261 
2262  return p_buf;
2263 }
2264 
2265 
2266 
2267 // get the name of a column or construct one
2268 static const char* getColName(
2269  const SPxLPBase<Real>& p_lp,
2270  int p_idx,
2271  const NameSet* p_cnames,
2272  char* p_buf
2273 )
2274 {
2275  assert(p_buf != 0);
2276  assert(p_idx >= 0);
2277  assert(p_idx < p_lp.nCols());
2278 
2279  if(p_cnames != 0)
2280  {
2281  DataKey key = p_lp.cId(p_idx);
2282 
2283  if(p_cnames->has(key))
2284  return (*p_cnames)[key];
2285  }
2286 
2287  spxSnprintf(p_buf, 16, "x%d", p_idx);
2288 
2289  return p_buf;
2290 }
2291 
2292 
2293 
2294 // write an SVector
2295 #define NUM_ENTRIES_PER_LINE 5
2296 static void LPFwriteSVector(
2297  const SPxLPBase<Real>& p_lp, ///< the LP
2298  std::ostream& p_output, ///< output stream
2299  const NameSet* p_cnames, ///< column names
2300  const SVectorBase<Real>& p_svec) ///< vector to write
2301 {
2302 
2303  char name[16];
2304  int num_coeffs = 0;
2305 
2306  for(int j = 0; j < p_lp.nCols(); ++j)
2307  {
2308  const Real coeff = p_svec[j];
2309 
2310  if(coeff == 0)
2311  continue;
2312 
2313  if(num_coeffs == 0)
2314  p_output << coeff << " " << getColName(p_lp, j, p_cnames, name);
2315  else
2316  {
2317  // insert a line break every NUM_ENTRIES_PER_LINE columns
2318  if(num_coeffs % NUM_ENTRIES_PER_LINE == 0)
2319  p_output << "\n\t";
2320 
2321  if(coeff < 0)
2322  p_output << " - " << -coeff;
2323  else
2324  p_output << " + " << coeff;
2325 
2326  p_output << " " << getColName(p_lp, j, p_cnames, name);
2327  }
2328 
2329  ++num_coeffs;
2330  }
2331 }
2332 
2333 
2334 
2335 // write the objective
2336 static void LPFwriteObjective(
2337  const SPxLPBase<Real>& p_lp, ///< the LP
2338  std::ostream& p_output, ///< output stream
2339  const NameSet* p_cnames ///< column names
2340 )
2341 {
2342 
2343  const int sense = p_lp.spxSense();
2344 
2345  p_output << ((sense == SPxLPBase<Real>::MINIMIZE) ? "Minimize\n" : "Maximize\n");
2346  p_output << " obj: ";
2347 
2348  const VectorBase<Real>& obj = p_lp.maxObj();
2349  DSVectorBase<Real> svec(obj.dim());
2350  svec.operator = (obj);
2351  svec *= Real(sense);
2352  LPFwriteSVector(p_lp, p_output, p_cnames, svec);
2353  p_output << "\n";
2354 }
2355 
2356 
2357 
2358 // write non-ranged rows
2359 static void LPFwriteRow(
2360  const SPxLPBase<Real>& p_lp, ///< the LP
2361  std::ostream& p_output, ///< output stream
2362  const NameSet* p_cnames, ///< column names
2363  const SVectorBase<Real>& p_svec, ///< vector of the row
2364  const Real& p_lhs, ///< lhs of the row
2365  const Real& p_rhs ///< rhs of the row
2366 )
2367 {
2368 
2369  LPFwriteSVector(p_lp, p_output, p_cnames, p_svec);
2370 
2371  if(p_lhs == p_rhs)
2372  p_output << " = " << p_rhs;
2373  else if(p_lhs <= -infinity)
2374  p_output << " <= " << p_rhs;
2375  else
2376  {
2377  assert(p_rhs >= infinity);
2378  p_output << " >= " << p_lhs;
2379  }
2380 
2381  p_output << "\n";
2382 }
2383 
2384 
2385 
2386 // write all rows
2387 static void LPFwriteRows(
2388  const SPxLPBase<Real>& p_lp, ///< the LP
2389  std::ostream& p_output, ///< output stream
2390  const NameSet* p_rnames, ///< row names
2391  const NameSet* p_cnames ///< column names
2392 )
2393 {
2394 
2395  char name[16];
2396 
2397  p_output << "Subject To\n";
2398 
2399  for(int i = 0; i < p_lp.nRows(); ++i)
2400  {
2401  const Real lhs = p_lp.lhs(i);
2402  const Real rhs = p_lp.rhs(i);
2403 
2404  if(lhs > -infinity && rhs < infinity && lhs != rhs)
2405  {
2406  // ranged row -> write two non-ranged rows
2407  p_output << " " << LPFgetRowName(p_lp, i, p_rnames, name, i) << "_1 : ";
2408  LPFwriteRow(p_lp, p_output, p_cnames, p_lp.rowVector(i), lhs, infinity);
2409 
2410  p_output << " " << LPFgetRowName(p_lp, i, p_rnames, name, i) << "_2 : ";
2411  LPFwriteRow(p_lp, p_output, p_cnames, p_lp.rowVector(i), -infinity, rhs);
2412  }
2413  else
2414  {
2415  p_output << " " << LPFgetRowName(p_lp, i, p_rnames, name, i) << " : ";
2416  LPFwriteRow(p_lp, p_output, p_cnames, p_lp.rowVector(i), lhs, rhs);
2417  }
2418  }
2419 }
2420 
2421 
2422 
2423 // write the variable bounds
2424 // (the default bounds 0 <= x <= infinity are not written)
2425 static void LPFwriteBounds(
2426  const SPxLPBase<Real>& p_lp, ///< the LP to write
2427  std::ostream& p_output, ///< output stream
2428  const NameSet* p_cnames ///< column names
2429 )
2430 {
2431 
2432  char name[16];
2433 
2434  p_output << "Bounds\n";
2435 
2436  for(int j = 0; j < p_lp.nCols(); ++j)
2437  {
2438  const Real lower = p_lp.lower(j);
2439  const Real upper = p_lp.upper(j);
2440 
2441  if(lower == upper)
2442  {
2443  p_output << " " << getColName(p_lp, j, p_cnames, name) << " = " << upper << '\n';
2444  }
2445  else if(lower > -infinity)
2446  {
2447  if(upper < infinity)
2448  {
2449  // range bound
2450  if(lower != 0)
2451  p_output << " " << lower << " <= "
2452  << getColName(p_lp, j, p_cnames, name)
2453  << " <= " << upper << '\n';
2454  else
2455  p_output << " " << getColName(p_lp, j, p_cnames, name)
2456  << " <= " << upper << '\n';
2457  }
2458  else if(lower != 0)
2459  p_output << " " << lower << " <= "
2460  << getColName(p_lp, j, p_cnames, name)
2461  << '\n';
2462  }
2463  else if(upper < infinity)
2464  p_output << " -Inf <= "
2465  << getColName(p_lp, j, p_cnames, name)
2466  << " <= " << upper << '\n';
2467  else
2468  p_output << " " << getColName(p_lp, j, p_cnames, name)
2469  << " free\n";
2470  }
2471 }
2472 
2473 
2474 
2475 // write the generals section
2476 static void LPFwriteGenerals(
2477  const SPxLPBase<Real>& p_lp, ///< the LP to write
2478  std::ostream& p_output, ///< output stream
2479  const NameSet* p_cnames, ///< column names
2480  const DIdxSet* p_intvars ///< integer variables
2481 )
2482 {
2483 
2484  char name[16];
2485 
2486  if(p_intvars == NULL || p_intvars->size() <= 0)
2487  return; // no integer variables
2488 
2489  p_output << "Generals\n";
2490 
2491  for(int j = 0; j < p_lp.nCols(); ++j)
2492  if(p_intvars->pos(j) >= 0)
2493  p_output << " " << getColName(p_lp, j, p_cnames, name) << "\n";
2494 }
2495 
2496 
2497 
2498 /// Write LP in LP Format.
2499 template <>
2501  std::ostream& p_output, ///< output stream
2502  const NameSet* p_rnames, ///< row names
2503  const NameSet* p_cnames, ///< column names
2504  const DIdxSet* p_intvars ///< integer variables
2505 ) const
2506 {
2507  SPxOut::setScientific(p_output, 16);
2508 
2509  LPFwriteObjective(*this, p_output, p_cnames);
2510  LPFwriteRows(*this, p_output, p_rnames, p_cnames);
2511  LPFwriteBounds(*this, p_output, p_cnames);
2512  LPFwriteGenerals(*this, p_output, p_cnames, p_intvars);
2513 
2514  p_output << "End" << std::endl;
2515 }
2516 
2517 
2518 
2519 // ---------------------------------------------------------------------------------------------------------------------
2520 // Specialization for writing MPS format
2521 // ---------------------------------------------------------------------------------------------------------------------
2522 
2523 static void MPSwriteRecord(
2524  std::ostream& os,
2525  const char* indicator,
2526  const char* name,
2527  const char* name1 = 0,
2528  const Real value1 = 0.0,
2529  const char* name2 = 0,
2530  const Real value2 = 0.0
2531 )
2532 {
2533  char buf[81];
2534 
2535  spxSnprintf(buf, sizeof(buf), " %-2.2s %-8.8s", (indicator == 0) ? "" : indicator,
2536  (name == 0) ? "" : name);
2537  os << buf;
2538 
2539  if(name1 != 0)
2540  {
2541  spxSnprintf(buf, sizeof(buf), "%-8.8s %.15" REAL_FORMAT, name1, value1);
2542  os << buf;
2543 
2544  if(name2 != 0)
2545  {
2546  spxSnprintf(buf, sizeof(buf), " %-8.8s %.15" REAL_FORMAT, name2, value2);
2547  os << buf;
2548  }
2549  }
2550 
2551  os << std::endl;
2552 }
2553 
2554 
2555 
2556 static Real MPSgetRHS(Real left, Real right)
2557 {
2558  Real rhsval;
2559 
2560  if(left > -infinity) /// This includes ranges
2561  rhsval = left;
2562  else if(right < infinity)
2563  rhsval = right;
2564  else
2565  throw SPxInternalCodeException("XMPSWR01 This should never happen.");
2566 
2567  return rhsval;
2568 }
2569 
2570 
2571 
2572 static const char* MPSgetRowName(
2573  const SPxLPBase<Real>& lp,
2574  int idx,
2575  const NameSet* rnames,
2576  char* buf
2577 )
2578 {
2579  assert(buf != 0);
2580  assert(idx >= 0);
2581  assert(idx < lp.nRows());
2582 
2583  if(rnames != 0)
2584  {
2585  DataKey key = lp.rId(idx);
2586 
2587  if(rnames->has(key))
2588  return (*rnames)[key];
2589  }
2590 
2591  spxSnprintf(buf, 16, "C%d", idx);
2592 
2593  return buf;
2594 }
2595 
2596 
2597 
2598 /// Write LP in MPS format.
2599 /** @note There will always be a BOUNDS section, even if there are no bounds.
2600  */
2601 template <>
2603  std::ostream& p_output, ///< output stream.
2604  const NameSet* p_rnames, ///< row names.
2605  const NameSet* p_cnames, ///< column names.
2606  const DIdxSet* p_intvars ///< integer variables.
2607 ) const
2608 {
2609 
2610  const char* indicator;
2611  char name [16];
2612  char name1[16];
2613  char name2[16];
2614  bool has_ranges = false;
2615  int i;
2616  int k;
2617 
2618  SPxOut::setScientific(p_output, 16);
2619  // --- NAME Section ---
2620  p_output << "NAME MPSDATA" << std::endl;
2621 
2622  // --- ROWS Section ---
2623  p_output << "ROWS" << std::endl;
2624 
2625  for(i = 0; i < nRows(); i++)
2626  {
2627  if(lhs(i) == rhs(i))
2628  indicator = "E";
2629  else if((lhs(i) > -infinity) && (rhs(i) < infinity))
2630  {
2631  indicator = "E";
2632  has_ranges = true;
2633  }
2634  else if(lhs(i) > -infinity)
2635  indicator = "G";
2636  else if(rhs(i) < infinity)
2637  indicator = "L";
2638  else
2639  throw SPxInternalCodeException("XMPSWR02 This should never happen.");
2640 
2641  MPSwriteRecord(p_output, indicator, MPSgetRowName(*this, i, p_rnames, name));
2642  }
2643 
2644  MPSwriteRecord(p_output, "N", "MINIMIZE");
2645 
2646  // --- COLUMNS Section ---
2647  p_output << "COLUMNS" << std::endl;
2648 
2649  bool has_intvars = (p_intvars != 0) && (p_intvars->size() > 0);
2650 
2651  for(int j = 0; j < (has_intvars ? 2 : 1); j++)
2652  {
2653  bool is_intrun = has_intvars && (j == 1);
2654 
2655  if(is_intrun)
2656  p_output << " MARK0001 'MARKER' 'INTORG'" << std::endl;
2657 
2658  for(i = 0; i < nCols(); i++)
2659  {
2660  bool is_intvar = has_intvars && (p_intvars->pos(i) >= 0);
2661 
2662  if((is_intrun && !is_intvar) || (!is_intrun && is_intvar))
2663  continue;
2664 
2665  const SVectorBase<Real>& col = colVector(i);
2666  int colsize2 = (col.size() / 2) * 2;
2667 
2668  assert(colsize2 % 2 == 0);
2669 
2670  for(k = 0; k < colsize2; k += 2)
2671  MPSwriteRecord(p_output, 0, getColName(*this, i, p_cnames, name),
2672  MPSgetRowName(*this, col.index(k), p_rnames, name1), col.value(k),
2673  MPSgetRowName(*this, col.index(k + 1), p_rnames, name2), col.value(k + 1));
2674 
2675  if(colsize2 != col.size())
2676  MPSwriteRecord(p_output, 0, getColName(*this, i, p_cnames, name),
2677  MPSgetRowName(*this, col.index(k), p_rnames, name1), col.value(k));
2678 
2679  if(isNotZero(maxObj(i)))
2680  MPSwriteRecord(p_output, 0, getColName(*this, i, p_cnames, name), "MINIMIZE", -maxObj(i));
2681  }
2682 
2683  if(is_intrun)
2684  p_output << " MARK0001 'MARKER' 'INTEND'" << std::endl;
2685  }
2686 
2687  // --- RHS Section ---
2688  p_output << "RHS" << std::endl;
2689 
2690  i = 0;
2691 
2692  while(i < nRows())
2693  {
2694  Real rhsval1 = 0.0;
2695  Real rhsval2 = 0.0;
2696 
2697  for(; i < nRows(); i++)
2698  if((rhsval1 = MPSgetRHS(lhs(i), rhs(i))) != 0.0)
2699  break;
2700 
2701  if(i < nRows())
2702  {
2703  for(k = i + 1; k < nRows(); k++)
2704  {
2705  if((rhsval2 = MPSgetRHS(lhs(k), rhs(k))) != 0.0)
2706  break;
2707  }
2708 
2709  if(k < nRows())
2710  {
2711  MPSwriteRecord(p_output, 0, "RHS", MPSgetRowName(*this, i, p_rnames, name1), rhsval1,
2712  MPSgetRowName(*this, k, p_rnames, name2), rhsval2);
2713  }
2714  else
2715  MPSwriteRecord(p_output, 0, "RHS", MPSgetRowName(*this, i, p_rnames, name1), rhsval1);
2716 
2717  i = k + 1;
2718  }
2719  }
2720 
2721  // --- RANGES Section ---
2722  if(has_ranges)
2723  {
2724  p_output << "RANGES" << std::endl;
2725 
2726  for(i = 0; i < nRows(); i++)
2727  {
2728  if((lhs(i) > -infinity) && (rhs(i) < infinity))
2729  MPSwriteRecord(p_output, "", "RANGE", MPSgetRowName(*this, i, p_rnames, name1), rhs(i) - lhs(i));
2730  }
2731  }
2732 
2733  // --- BOUNDS Section ---
2734  p_output << "BOUNDS" << std::endl;
2735 
2736  for(i = 0; i < nCols(); i++)
2737  {
2738  // skip variables that do not appear in the objective function or any constraint
2739  const SVectorBase<Real>& col = colVector(i);
2740 
2741  if(col.size() == 0 && isZero(maxObj(i)))
2742  continue;
2743 
2744  if(lower(i) == upper(i))
2745  {
2746  MPSwriteRecord(p_output, "FX", "BOUND", getColName(*this, i, p_cnames, name1), lower(i));
2747  continue;
2748  }
2749 
2750  if((lower(i) <= -infinity) && (upper(i) >= infinity))
2751  {
2752  MPSwriteRecord(p_output, "FR", "BOUND", getColName(*this, i, p_cnames, name1));
2753  continue;
2754  }
2755 
2756  if(lower(i) != 0.0)
2757  {
2758  if(lower(i) > -infinity)
2759  MPSwriteRecord(p_output, "LO", "BOUND", getColName(*this, i, p_cnames, name1), lower(i));
2760  else
2761  MPSwriteRecord(p_output, "MI", "BOUND", getColName(*this, i, p_cnames, name1));
2762  }
2763 
2764  if(has_intvars && (p_intvars->pos(i) >= 0))
2765  {
2766  // Integer variables have default upper bound 1.0, but we should write
2767  // it nevertheless since CPLEX seems to assume infinity otherwise.
2768  MPSwriteRecord(p_output, "UP", "BOUND", getColName(*this, i, p_cnames, name1), upper(i));
2769  }
2770  else
2771  {
2772  // Continous variables have default upper bound infinity
2773  if(upper(i) < infinity)
2774  MPSwriteRecord(p_output, "UP", "BOUND", getColName(*this, i, p_cnames, name1), upper(i));
2775  }
2776  }
2777 
2778  // --- ENDATA Section ---
2779  p_output << "ENDATA" << std::endl;
2780 
2781  // Output warning when writing a maximisation problem
2782  if(spxSense() == SPxLPBase<Real>::MAXIMIZE)
2783  {
2784  MSG_WARNING((*spxout), (*spxout) <<
2785  "XMPSWR03 Warning: objective function inverted when writing maximization problem in MPS file format\n");
2786  }
2787 }
2788 
2789 
2790 
2791 /// Building the dual problem from a given LP
2792 /// @note primalRows must be as large as the number of unranged primal rows + 2 * the number of ranged primal rows.
2793 /// dualCols must have the identical size to the primal rows.
2794 template < >
2796  SPxColId primalColIds[],
2797  SPxRowId dualRowIds[], SPxColId dualColIds[], int* nprimalrows, int* nprimalcols, int* ndualrows,
2798  int* ndualcols)
2799 {
2800  // Setting up the primalrowids and dualcolids arrays if not given as parameters
2801  if(primalRowIds == 0 || primalColIds == 0 || dualRowIds == 0 || dualColIds == 0)
2802  {
2803  DataArray < SPxRowId > primalrowids(2 * nRows());
2804  DataArray < SPxColId > primalcolids(2 * nCols());
2805  DataArray < SPxRowId > dualrowids(2 * nCols());
2806  DataArray < SPxColId > dualcolids(2 * nRows());
2807  int numprimalrows = 0;
2808  int numprimalcols = 0;
2809  int numdualrows = 0;
2810  int numdualcols = 0;
2811 
2812  buildDualProblem(dualLP, primalrowids.get_ptr(), primalcolids.get_ptr(), dualrowids.get_ptr(),
2813  dualcolids.get_ptr(), &numprimalrows, &numprimalcols, &numdualrows, &numdualcols);
2814 
2815  if(primalRowIds != 0)
2816  {
2817  primalRowIds = primalrowids.get_ptr();
2818  (*nprimalrows) = numprimalrows;
2819  }
2820 
2821  if(primalColIds != 0)
2822  {
2823  primalColIds = primalcolids.get_ptr();
2824  (*nprimalcols) = numprimalcols;
2825  }
2826 
2827  if(dualRowIds != 0)
2828  {
2829  dualRowIds = dualrowids.get_ptr();
2830  (*ndualrows) = numdualrows;
2831  }
2832 
2833  if(dualColIds != 0)
2834  {
2835  dualColIds = dualcolids.get_ptr();
2836  (*ndualcols) = numdualcols;
2837  }
2838 
2839  return;
2840  }
2841 
2842  // setting the sense of the dual LP
2843  if(spxSense() == MINIMIZE)
2844  dualLP.changeSense(MAXIMIZE);
2845  else
2846  dualLP.changeSense(MINIMIZE);
2847 
2848  LPRowSetBase<Real> dualrows(nCols());
2849  LPColSetBase<Real> dualcols(nRows());
2850  DSVectorBase<Real> col(1);
2851 
2852  int numAddedRows = 0;
2853  int numVarBoundCols = 0;
2854  int primalrowsidx = 0;
2855  int primalcolsidx = 0;
2856 
2857  for(int i = 0; i < nCols(); ++i)
2858  {
2859  primalColIds[primalcolsidx] = cId(i);
2860  primalcolsidx++;
2861 
2862  if(lower(i) <= -infinity && upper(i) >= infinity) // unrestricted variables
2863  {
2864  dualrows.create(0, obj(i), obj(i));
2865  numAddedRows++;
2866  }
2867  else if(lower(i) <= -infinity) // no lower bound is set, indicating a <= 0 variable
2868  {
2869  if(isZero(upper(i))) // standard bound variable
2870  {
2871  if(spxSense() == MINIMIZE)
2872  dualrows.create(0, obj(i), infinity);
2873  else
2874  dualrows.create(0, -infinity, obj(i));
2875  }
2876  else // additional upper bound on the variable
2877  {
2878  col.add(numAddedRows, 1.0);
2879 
2880  if(spxSense() == MINIMIZE)
2881  {
2882  dualrows.create(0, obj(i), obj(i));
2883  dualcols.add(upper(i), -infinity, col, 0.0);
2884  }
2885  else
2886  {
2887  dualrows.create(0, obj(i), obj(i));
2888  dualcols.add(upper(i), 0.0, col, infinity);
2889  }
2890 
2891  col.clear();
2892 
2893  numVarBoundCols++;
2894  }
2895 
2896  numAddedRows++;
2897  }
2898  else if(upper(i) >= infinity) // no upper bound set, indicating a >= 0 variable
2899  {
2900  if(isZero(lower(i))) // standard bound variable
2901  {
2902  if(spxSense() == MINIMIZE)
2903  dualrows.create(0, -infinity, obj(i));
2904  else
2905  dualrows.create(0, obj(i), infinity);
2906  }
2907  else // additional lower bound on the variable
2908  {
2909  col.add(numAddedRows, 1.0);
2910 
2911  if(spxSense() == MINIMIZE)
2912  {
2913  dualrows.create(0, obj(i), obj(i));
2914  dualcols.add(lower(i), 0.0, col, infinity);
2915  }
2916  else
2917  {
2918  dualrows.create(0, obj(i), obj(i));
2919  dualcols.add(lower(i), -infinity, col, 0.0);
2920  }
2921 
2922  col.clear();
2923 
2924  numVarBoundCols++;
2925  }
2926 
2927  numAddedRows++;
2928  }
2929  else if(NE(lower(i), upper(i))) // a boxed variable
2930  {
2931  if(isZero(lower(i))) // variable bounded between 0 and upper(i)
2932  {
2933  col.add(numAddedRows, 1.0);
2934 
2935  if(spxSense() == MINIMIZE)
2936  {
2937  dualrows.create(0, -infinity, obj(i));
2938  dualcols.add(upper(i), -infinity, col, 0.0);
2939  }
2940  else
2941  {
2942  dualrows.create(0, obj(i), infinity);
2943  dualcols.add(upper(i), 0.0, col, infinity);
2944  }
2945 
2946  col.clear();
2947 
2948  numVarBoundCols++;
2949  }
2950  else if(isZero(upper(i))) // variable bounded between lower(i) and 0
2951  {
2952  col.add(numAddedRows, 1.0);
2953 
2954  if(spxSense() == MINIMIZE)
2955  {
2956  dualrows.create(0, obj(i), infinity);
2957  dualcols.add(lower(i), 0.0, col, infinity);
2958  }
2959  else
2960  {
2961  dualrows.create(0, -infinity, obj(i));
2962  dualcols.add(lower(i), -infinity, col, 0.0);
2963  }
2964 
2965  col.clear();
2966 
2967  numVarBoundCols++;
2968  }
2969  else // variable bounded between lower(i) and upper(i)
2970  {
2971  dualrows.create(0, obj(i), obj(i));
2972 
2973  col.add(numAddedRows, 1.0);
2974 
2975  if(spxSense() == MINIMIZE)
2976  {
2977  dualcols.add(lower(i), 0.0, col, infinity);
2978  dualcols.add(upper(i), -infinity, col, 0.0);
2979  }
2980  else
2981  {
2982  dualcols.add(lower(i), -infinity, col, 0.0);
2983  dualcols.add(upper(i), 0.0, col, infinity);
2984  }
2985 
2986  col.clear();
2987 
2988  numVarBoundCols += 2;
2989  }
2990 
2991  numAddedRows++;
2992  }
2993  else
2994  {
2995  assert(lower(i) == upper(i));
2996 
2997  dualrows.create(0, obj(i), obj(i));
2998 
2999  col.add(numAddedRows, 1.0);
3000  dualcols.add(lower(i), 0, col, infinity);
3001  dualcols.add(lower(i), -infinity, col, 0);
3002  col.clear();
3003 
3004  numVarBoundCols += 2;
3005  numAddedRows++;
3006  }
3007  }
3008 
3009  // adding the empty rows to the dual LP
3010  dualLP.addRows(dualrows);
3011 
3012  // setting the dual row ids for the related primal cols.
3013  // this assumes that the rows are added in sequential order.
3014  for(int i = 0; i < primalcolsidx; i++)
3015  dualRowIds[i] = dualLP.rId(i);
3016 
3017  (*nprimalcols) = primalcolsidx;
3018  (*ndualrows) = primalcolsidx;
3019 
3020  // iterating over each of the rows to create dual columns
3021  for(int i = 0; i < nRows(); ++i)
3022  {
3023  // checking the type of the row
3024  switch(rowType(i))
3025  {
3026  case LPRowBase<Real>::RANGE: // range constraint, requires the addition of two dual variables
3027  assert(lhs(i) > -infinity);
3028  assert(rhs(i) < infinity);
3029 
3030  if(spxSense() == MINIMIZE)
3031  {
3032  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3033  primalrowsidx++;
3034  dualcols.add(lhs(i), 0.0, rowVector(i), infinity);
3035 
3036  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3037  primalrowsidx++;
3038  dualcols.add(rhs(i), -infinity, rowVector(i), 0.0);
3039  }
3040  else
3041  {
3042  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3043  primalrowsidx++;
3044  dualcols.add(lhs(i), -infinity, rowVector(i), 0.0);
3045 
3046  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3047  primalrowsidx++;
3048  dualcols.add(rhs(i), 0.0, rowVector(i), infinity);
3049  }
3050 
3051  break;
3052 
3053  case LPRowBase<Real>::GREATER_EQUAL: // >= constraint
3054  assert(lhs(i) > -infinity);
3055  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3056  primalrowsidx++;
3057 
3058  if(spxSense() == MINIMIZE)
3059  dualcols.add(lhs(i), 0.0, rowVector(i), infinity);
3060  else
3061  dualcols.add(lhs(i), -infinity, rowVector(i), 0.0);
3062 
3063  break;
3064 
3065  case LPRowBase<Real>::LESS_EQUAL: // <= constriant
3066  assert(rhs(i) < infinity);
3067  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3068  primalrowsidx++;
3069 
3070  if(spxSense() == MINIMIZE)
3071  dualcols.add(rhs(i), -infinity, rowVector(i), 0.0);
3072  else
3073  dualcols.add(rhs(i), 0.0, rowVector(i), infinity);
3074 
3075  break;
3076 
3077  case LPRowBase<Real>::EQUAL: // Equality constraint
3078  assert(EQ(lhs(i), rhs(i)));
3079  primalRowIds[primalrowsidx] = rId(i); // setting the rowid for the primal row
3080  primalrowsidx++;
3081  dualcols.add(rhs(i), -infinity, rowVector(i), infinity);
3082  break;
3083 
3084  default:
3085  throw SPxInternalCodeException("XLPFRD01 This should never happen.");
3086  }
3087  }
3088 
3089  // adding the filled columns to the dual LP
3090  dualLP.addCols(dualcols);
3091 
3092  // setting the dual column ids for the related primal rows.
3093  // this assumes that the columns are added in sequential order.
3094  for(int i = 0; i < primalrowsidx; i++)
3095  dualColIds[i] = dualLP.cId(i + numVarBoundCols);
3096 
3097  (*nprimalrows) = primalrowsidx;
3098  (*ndualcols) = primalrowsidx;
3099 }
3100 
3101 
3102 
3103 // ---------------------------------------------------------------------------------------------------------------------
3104 // Explicit instantiation
3105 // ---------------------------------------------------------------------------------------------------------------------
3106 
3107 template class SPxLPBase < Real >;
3108 
3109 } // namespace soplex
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:221
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:4102
bool isNotZero(Real a, Real eps=Param::epsilon())
returns true iff |a| > eps
Definition: spxdefines.h:418
void getRhsUnscaled(VectorBase< Real > &vec) const
Gets unscaled right hand side vector.
Exception class for things that should NEVER happen.This class is derived from the SoPlex exception b...
Definition: exceptions.h:109
static void MPSreadCols(MPSInput &mps, const LPRowSetBase< Real > &rset, const NameSet &rnames, LPColSetBase< Real > &cset, NameSet &cnames, DIdxSet *intvars)
Process COLUMNS section.
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
Safe arrays of data objects.Class DataArray provides safe arrays of Data Objects. For general C++ obj...
Definition: dataarray.h:63
const char * field4() const
Definition: mpsinput.h:170
#define INIT_NZOS
initialy allocated non zeros.
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
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
int num() const
returns nr. of names in NameSet.
Definition: nameset.h:168
void entryIgnored(const char *what, const char *what_name, const char *entity, const char *entity_name)
Definition: mpsinput.h:244
static void MPSreadRanges(MPSInput &mps, LPRowSetBase< Real > &rset, const NameSet &rnames, SPxOut *spxout)
Process RANGES section.
Read MPS format files.
T * get_ptr()
get a C pointer to the data.
Definition: dataarray.h:110
const VectorBase< R > & lhs() const
Returns the vector of lhs values.
Definition: lprowsetbase.h:95
int size() const
Number of used indices.
Definition: svectorbase.h:153
static Real LPFreadValue(char *&pos, SPxOut *spxout)
Read the next number and advance pos.
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.
#define INIT_COLS
Read LP in MPS File Format.
bool NE(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| > eps
Definition: spxdefines.h:382
void syntaxError()
Definition: mpsinput.h:237
static Real MPSgetRHS(Real left, Real right)
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
static void LPFwriteSVector(const SPxLPBase< Real > &p_lp, std::ostream &p_output, const NameSet *p_cnames, const SVectorBase< Real > &p_svec)
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
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 void LPFwriteGenerals(const SPxLPBase< Real > &p_lp, std::ostream &p_output, const NameSet *p_cnames, const DIdxSet *p_intvars)
VectorBase< R > & lower_w()
Returns vector of lower bound values.
Definition: lpcolsetbase.h:136
#define REAL_FORMAT
Definition: spxdefines.h:222
void add(const LPRowBase< R > &row)
Definition: lprowsetbase.h:328
VectorBase< R > & upper_w()
Returns vector of upper bound values.
Definition: lpcolsetbase.h:172
static void LPFwriteRow(const SPxLPBase< Real > &p_lp, std::ostream &p_output, const NameSet *p_cnames, const SVectorBase< Real > &p_svec, const Real &p_lhs, const Real &p_rhs)
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
static void LPFwriteObjective(const SPxLPBase< Real > &p_lp, std::ostream &p_output, const NameSet *p_cnames)
static const char * getColName(const SPxLPBase< Real > &p_lp, int p_idx, const NameSet *p_cnames, char *p_buf)
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
static Real LPFreadInfinity(char *&pos)
bool readLine()
reads an MPS format data line and parse the fields.
Definition: mpsinput.cpp:58
static void MPSreadBounds(MPSInput &mps, LPColSetBase< Real > &cset, const NameSet &cnames, DIdxSet *intvars, SPxOut *spxout)
Process BOUNDS section.
void getLowerUnscaled(DVector &vec) const
Gets unscaled lower bound vector.
static bool LPFhasRowName(char *&pos, NameSet *rownames)
If buf start with "name:" store the name in rownames and advance pos.
#define NUM_ENTRIES_PER_LINE
double Real
Definition: spxdefines.h:218
static void LPFwriteRows(const SPxLPBase< Real > &p_lp, std::ostream &p_output, const NameSet *p_rnames, const NameSet *p_cnames)
const char * probName() const
Definition: mpsinput.h:180
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
Wrapper for several output streams. A verbosity level is used to decide which stream to use and wheth...
Definition: spxout.h:63
virtual void addRows(const LPRowSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:643
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
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:255
const char * field3() const
Definition: mpsinput.h:165
static int LPFreadColName(char *&pos, NameSet *colnames, LPColSetBase< Real > &colset, const LPColBase< Real > *emptycol, SPxOut *spxout)
Read the next column name from the input.
static const char * LPFgetRowName(const SPxLPBase< Real > &p_lp, int p_idx, const NameSet *p_rnames, char *p_buf, int p_num_written_rows)
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
void setObjSense(Sense sense)
Definition: mpsinput.h:227
const char * objName() const
Definition: mpsinput.h:185
static void MPSreadRows(MPSInput &mps, LPRowSetBase< Real > &rset, NameSet &rnames, SPxOut *spxout)
Process ROWS section.
(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 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
bool EQ(Real a, Real b, Real eps=Param::epsilon())
returns true iff |a-b| <= eps
Definition: spxdefines.h:376
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.
bool isInteger() const
Definition: mpsinput.h:200
static void LPFwriteBounds(const SPxLPBase< Real > &p_lp, std::ostream &p_output, const NameSet *p_cnames)
static void MPSreadObjname(MPSInput &mps)
Process OBJNAME section. This Section is an ILOG extension.
void clear()
Remove all indices.
Definition: svectorbase.h:431
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:80
#define LPF_MAX_LINE_LEN
maximum length of a line (8190 + \n + \0)
Set of LP columns.Class LPColSetBase implements a set of LPColBase%s. Unless for memory limitations...
Definition: lpcolsetbase.h:43
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
LP scaling base class.
void setRowVector(const DSVectorBase< R > &p_vec)
access constraint row vector.
Definition: lprowbase.h:253
static void MPSreadRhs(MPSInput &mps, LPRowSetBase< Real > &rset, const NameSet &rnames, SPxOut *spxout)
Process RHS section.
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:206
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.
DVectorBase< Real > DVector
Definition: dvector.h:28
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 ?
virtual void changeSense(SPxSense sns)
Changes optimization sense to sns.
Definition: spxlpbase.h:1830
void getUpperUnscaled(DVector &vec) const
Gets unscaled upper bound vector.
const char * field5() const
Definition: mpsinput.h:175
void unscaleLP()
unscales the lp and clears basis
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
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:158
const char * field1() const
Definition: mpsinput.h:155
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 ?
#define ROWS
Definition: spxmainsm.cpp:53
static const char * MPSgetRowName(const SPxLPBase< Real > &lp, int idx, const NameSet *rnames, char *buf)
Ids for LP rows.Class SPxRowId provides DataKeys for the row indices of an SPxLP. ...
Definition: spxid.h:55
bool isZero(Real a, Real eps=Param::epsilon())
returns true iff |a| <= eps
Definition: spxdefines.h:412
void setColVector(const SVectorBase< R > &p_vec)
Sets constraint column vector.
Definition: lpcolbase.h:154
void getLhsUnscaled(VectorBase< Real > &vec) const
Returns unscaled left hand side vector.
VectorBase< R > & rhs_w()
Returns the vector of rhs values (writeable).
Definition: lprowsetbase.h:137
const char * field2() const
Definition: mpsinput.h:160
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
SVectorBase< R > & create(int pnonzeros=0, const R &plhs=0, const R &prhs=1, const R &pobj=0, const int &pscaleExp=0)
Creates new LPRowBase with specified parameters and returns a reference to its row vector...
Definition: lprowsetbase.h:479
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:488
~NameSet()
destructor.
Definition: nameset.cpp:219
int num() const
Returns the number of LPColBases currently in LPColSetBase.
Definition: lpcolsetbase.h:82
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
virtual void addCols(const LPColSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:813
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)
static void MPSwriteRecord(std::ostream &os, const char *indicator, const char *name, const char *name1=0, const Real value1=0.0, const char *name2=0, const Real value2=0.0)