Scippy

SoPlex

Sequential object-oriented simPlex

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