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