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