Scippy

SoPlex

Sequential object-oriented simPlex

soplex.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-2015 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 soplex.cpp
17  * @brief Preconfigured SoPlex LP solver
18  */
19 
20 #ifndef SOPLEX_LEGACY
21 #include <assert.h>
22 #include "limits.h"
23 #include <iostream>
24 
25 #ifndef _MSC_VER
26 #include <strings.h>
27 #endif
28 
29 #include "soplex.h"
30 #include "spxfileio.h"
31 #include "spxgithash.h"
32 #include "statistics.h"
33 #include "mpsinput.h"
34 
35 /// maximum length of lines in settings file
36 #define SET_MAX_LINE_LEN 500
37 
38 #ifdef _MSC_VER
39 #define strncasecmp _strnicmp
40 #endif
41 
42 namespace soplex
43 {
44  /// class of parameter settings
46  {
47  public:
48  /// array of names for boolean parameters
50 
51  /// array of names for integer parameters
53 
54  /// array of names for real parameters
56 
57 #ifdef SOPLEX_WITH_RATIONALPARAM
58  /// array of names for rational parameters
59  static std::string _rationalParamName[SoPlex::RATIONALPARAM_COUNT];
60 #endif
61 
62  /// array of descriptions for boolean parameters
64 
65  /// array of descriptions for integer parameters
67 
68  /// array of descriptions for real parameters
70 
71 #ifdef SOPLEX_WITH_RATIONALPARAM
72  /// array of descriptions for rational parameters
73  static std::string _rationalParamDescription[SoPlex::RATIONALPARAM_COUNT];
74 #endif
75 
76  /// array of default values for boolean parameters
78 
79  /// array of default values for integer parameters
81 
82  /// array of default values for real parameters
84 
85 #ifdef SOPLEX_WITH_RATIONALPARAM
86  /// array of default values for rational parameters
87  static Rational _rationalParamDefault[SoPlex::RATIONALPARAM_COUNT];
88 #endif
89 
90  /// array of lower bounds for int parameter values
92 
93  /// array of upper bounds for int parameter values
95 
96  /// array of lower bounds for real parameter values
98 
99  /// array of upper bounds for real parameter values
101 
102 #ifdef SOPLEX_WITH_RATIONALPARAM
103  /// array of lower bounds for rational parameter values
104  static Rational _rationalParamLower[SoPlex::RATIONALPARAM_COUNT];
105 
106  /// array of upper bounds for rational parameter values
107  static Rational _rationalParamUpper[SoPlex::RATIONALPARAM_COUNT];
108 #endif
109 
110  /// have static arrays been initialized?
112 
113  /// array of current boolean parameter values
115 
116  /// array of current integer parameter values
118 
119  /// array of current real parameter values
121 
122 #ifdef SOPLEX_WITH_RATIONALPARAM
123  /// array of current rational parameter values
124  Rational _rationalParamValues[SoPlex::RATIONALPARAM_COUNT];
125 #endif
126 
127  /// default constructor initializing default settings
129  {
131  {
132  // should lifting be used to reduce range of nonzero matrix coefficients?
133  _boolParamName[SoPlex::LIFTING] = "lifting";
134  _boolParamDescription[SoPlex::LIFTING] = "should lifting be used to reduce range of nonzero matrix coefficients?";
136 
137  // should LP be transformed to equality form before a rational solve?
138  _boolParamName[SoPlex::EQTRANS] = "eqtrans";
139  _boolParamDescription[SoPlex::EQTRANS] = "should LP be transformed to equality form before a rational solve?";
141 
142  // should dual infeasibility be tested in order to try to return a dual solution even if primal infeasible?
143  _boolParamName[SoPlex::TESTDUALINF] = "testdualinf";
144  _boolParamDescription[SoPlex::TESTDUALINF] = "should dual infeasibility be tested in order to try to return a dual solution even if primal infeasible?";
146 
147  // should a rational factorization be performed after iterative refinement?
148  _boolParamName[SoPlex::RATFAC] = "ratfac";
149  _boolParamDescription[SoPlex::RATFAC] = "should a rational factorization be performed after iterative refinement?";
151 
152  // should cycling solutions be accepted during iterative refinement?
153  _boolParamName[SoPlex::ACCEPTCYCLING] = "acceptcycling";
154  _boolParamDescription[SoPlex::ACCEPTCYCLING] = "should cycling solutions be accepted during iterative refinement?";
156 
157  // apply rational reconstruction after each iterative refinement?
158  _boolParamName[SoPlex::RATREC] = "ratrec";
159  _boolParamDescription[SoPlex::RATREC] = "apply rational reconstruction after each iterative refinement?";
161 
162  // round scaling factors for iterative refinement to powers of two?
163  _boolParamName[SoPlex::POWERSCALING] = "powerscaling";
164  _boolParamDescription[SoPlex::POWERSCALING] = "round scaling factors for iterative refinement to powers of two?";
166 
167  // continue iterative refinement with exact basic solution if not optimal?
168  _boolParamName[SoPlex::RATFACJUMP] = "ratfacjump";
169  _boolParamDescription[SoPlex::RATFACJUMP] = "continue iterative refinement with exact basic solution if not optimal?";
171 
172  // should feasibility be tested with relaxed bounds and sides?
173  _boolParamName[SoPlex::FEASRELAX] = "feasrelax";
174  _boolParamDescription[SoPlex::FEASRELAX] = "should feasibility be tested with relaxed bounds and sides?";
176 
177  // use bound flipping also for row representation?
178  _boolParamName[SoPlex::ROWBOUNDFLIPS] = "rowboundflips";
179  _boolParamDescription[SoPlex::ROWBOUNDFLIPS] = "use bound flipping also for row representation?";
181 
182  // objective sense
183  _intParamName[SoPlex::OBJSENSE] = "objsense";
184  _intParamDescription[SoPlex::OBJSENSE] = "objective sense (-1 - minimize, +1 - maximize)";
188 
189  // type of computational form, i.e., column or row representation
190  _intParamName[SoPlex::REPRESENTATION] = "representation";
191  _intParamDescription[SoPlex::REPRESENTATION] = "type of computational form (0 - auto, 1 - column representation, 2 - row representation)";
195 
196  // type of algorithm, i.e., primal or dual
197  _intParamName[SoPlex::ALGORITHM] = "algorithm";
198  _intParamDescription[SoPlex::ALGORITHM] = "type of algorithm (0 - primal, 1 - dual)";
202 
203  // type of LU update
204  _intParamName[SoPlex::FACTOR_UPDATE_TYPE] = "factor_update_type";
205  _intParamDescription[SoPlex::FACTOR_UPDATE_TYPE] = "type of LU update (0 - eta update, 1 - Forrest-Tomlin update)";
209 
210  ///@todo which value?
211  // maximum number of updates without fresh factorization
212  _intParamName[SoPlex::FACTOR_UPDATE_MAX] = "factor_update_max";
213  _intParamDescription[SoPlex::FACTOR_UPDATE_MAX] = "maximum number of LU updates without fresh factorization";
217 
218  // iteration limit (-1 if unlimited)
219  _intParamName[SoPlex::ITERLIMIT] = "iterlimit";
220  _intParamDescription[SoPlex::ITERLIMIT] = "iteration limit (-1 - no limit)";
224 
225  // refinement limit (-1 if unlimited)
226  _intParamName[SoPlex::REFLIMIT] = "reflimit";
227  _intParamDescription[SoPlex::REFLIMIT] = "refinement limit (-1 - no limit)";
229  _intParamUpper[SoPlex::REFLIMIT] = INT_MAX;
231 
232  // stalling refinement limit (-1 if unlimited)
233  _intParamName[SoPlex::STALLREFLIMIT] = "stallreflimit";
234  _intParamDescription[SoPlex::STALLREFLIMIT] = "stalling refinement limit (-1 - no limit)";
238 
239  // display frequency
240  _intParamName[SoPlex::DISPLAYFREQ] = "displayfreq";
241  _intParamDescription[SoPlex::DISPLAYFREQ] = "display frequency";
245 
246  // verbosity level
247  _intParamName[SoPlex::VERBOSITY] = "verbosity";
248  _intParamDescription[SoPlex::VERBOSITY] = "verbosity level (0 - error, 1 - warning, 2 - debug, 3 - normal, 4 - high, 5 - full)";
252 
253  // type of simplifier
254  _intParamName[SoPlex::SIMPLIFIER] = "simplifier";
255  _intParamDescription[SoPlex::SIMPLIFIER] = "simplifier (0 - off, 1 - auto)";
259 
260  // type of scaler
261  _intParamName[SoPlex::SCALER] = "scaler";
262  _intParamDescription[SoPlex::SCALER] = "scaling (0 - off, 1 - uni-equilibrium, 2 - bi-equilibrium, 3 - geometric, 4 - iterated geometric)";
266 
267  // type of starter used to create crash basis
268  _intParamName[SoPlex::STARTER] = "starter";
269  _intParamDescription[SoPlex::STARTER] = "crash basis generated when starting from scratch (0 - none, 1 - weight, 2 - sum, 3 - vector)";
273 
274  // type of pricer
275  _intParamName[SoPlex::PRICER] = "pricer";
276  _intParamDescription[SoPlex::PRICER] = "pricing method (0 - auto, 1 - dantzig, 2 - parmult, 3 - devex, 4 - quicksteep, 5 - steep)";
280 
281  // type of ratio test
282  _intParamName[SoPlex::RATIOTESTER] = "ratiotester";
283  _intParamDescription[SoPlex::RATIOTESTER] = "method for ratio test (0 - textbook, 1 - harris, 2 - fast, 3 - boundflipping)";
287 
288  // mode for synchronizing real and rational LP
289  _intParamName[SoPlex::SYNCMODE] = "syncmode";
290  _intParamDescription[SoPlex::SYNCMODE] = "mode for synchronizing real and rational LP (0 - store only real LP, 1 - auto, 2 - manual)";
294 
295  // mode for reading LP files
296  _intParamName[SoPlex::READMODE] = "readmode";
297  _intParamDescription[SoPlex::READMODE] = "mode for reading LP files (0 - floating-point, 1 - rational)";
301 
302  // mode for iterative refinement strategy
303  _intParamName[SoPlex::SOLVEMODE] = "solvemode";
304  _intParamDescription[SoPlex::SOLVEMODE] = "mode for iterative refinement strategy (0 - floating-point solve, 1 - auto, 2 - exact rational solve)";
308 
309  // mode for iterative refinement strategy
310  _intParamName[SoPlex::CHECKMODE] = "checkmode";
311  _intParamDescription[SoPlex::CHECKMODE] = "mode for a posteriori feasibility checks (0 - floating-point check, 1 - auto, 2 - exact rational check)";
315 
316  // type of timing
317  _intParamName[SoPlex::TIMER] = "timer";
318  _intParamDescription[SoPlex::TIMER] = "type of timer (1 - cputime, aka. usertime, 2 - wallclock time, 0 - no timing)";
322 
323  // mode for hyper sparse pricing
324  _intParamName[SoPlex::HYPER_PRICING] = "hyperpricing";
325  _intParamDescription[SoPlex::HYPER_PRICING] = "mode for hyper sparse pricing (0 - off, 1 - auto, 2 - always)";
329 
330  // minimum number of stalling refinements since last pivot to trigger rational factorization
331  _intParamName[SoPlex::RATFAC_MINSTALLS] = "ratfac_minstalls";
332  _intParamDescription[SoPlex::RATFAC_MINSTALLS] = "minimum number of stalling refinements since last pivot to trigger rational factorization";
336 
337  // primal feasibility tolerance
338  _realParamName[SoPlex::FEASTOL] = "feastol";
339  _realParamDescription[SoPlex::FEASTOL] = "primal feasibility tolerance";
343 
344  // dual feasibility tolerance
345  _realParamName[SoPlex::OPTTOL] = "opttol";
346  _realParamDescription[SoPlex::OPTTOL] = "dual feasibility tolerance";
350 
351  ///@todo define suitable values depending on Real type
352  // general zero tolerance
353  _realParamName[SoPlex::EPSILON_ZERO] = "epsilon_zero";
354  _realParamDescription[SoPlex::EPSILON_ZERO] = "general zero tolerance";
358 
359  ///@todo define suitable values depending on Real type
360  // zero tolerance used in factorization
361  _realParamName[SoPlex::EPSILON_FACTORIZATION] = "epsilon_factorization";
362  _realParamDescription[SoPlex::EPSILON_FACTORIZATION] = "zero tolerance used in factorization";
366 
367  ///@todo define suitable values depending on Real type
368  // zero tolerance used in update of the factorization
369  _realParamName[SoPlex::EPSILON_UPDATE] = "epsilon_update";
370  _realParamDescription[SoPlex::EPSILON_UPDATE] = "zero tolerance used in update of the factorization";
374 
375  ///@todo define suitable values depending on Real type
376  // pivot zero tolerance used in factorization
377  _realParamName[SoPlex::EPSILON_PIVOT] = "epsilon_pivot";
378  _realParamDescription[SoPlex::EPSILON_PIVOT] = "pivot zero tolerance used in factorization";
382 
383  ///@todo define suitable values depending on Real type
384  // infinity threshold
385  _realParamName[SoPlex::INFTY] = "infty";
386  _realParamDescription[SoPlex::INFTY] = "infinity threshold";
390 
391  // time limit in seconds (INFTY if unlimited)
392  _realParamName[SoPlex::TIMELIMIT] = "timelimit";
393  _realParamDescription[SoPlex::TIMELIMIT] = "time limit in seconds";
397 
398  // lower limit on objective value
399  _realParamName[SoPlex::OBJLIMIT_LOWER] = "objlimit_lower";
400  _realParamDescription[SoPlex::OBJLIMIT_LOWER] = "lower limit on objective value";
404 
405  // upper limit on objective value
406  _realParamName[SoPlex::OBJLIMIT_UPPER] = "objlimit_upper";
407  _realParamDescription[SoPlex::OBJLIMIT_UPPER] = "upper limit on objective value";
411 
412  // working tolerance for feasibility in floating-point solver during iterative refinement
413  _realParamName[SoPlex::FPFEASTOL] = "fpfeastol";
414  _realParamDescription[SoPlex::FPFEASTOL] = "working tolerance for feasibility in floating-point solver during iterative refinement";
418 
419  // working tolerance for optimality in floating-point solver during iterative refinement
420  _realParamName[SoPlex::FPOPTTOL] = "fpopttol";
421  _realParamDescription[SoPlex::FPOPTTOL] = "working tolerance for optimality in floating-point solver during iterative refinement";
425 
426  // maximum increase of scaling factors between refinements
427  _realParamName[SoPlex::MAXSCALEINCR] = "maxscaleincr";
428  _realParamDescription[SoPlex::MAXSCALEINCR] = "maximum increase of scaling factors between refinements";
432 
433  // lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated)
434  _realParamName[SoPlex::LIFTMINVAL] = "liftminval";
435  _realParamDescription[SoPlex::LIFTMINVAL] = "lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated)";
438  _realParamDefault[SoPlex::LIFTMINVAL] = 0.000976562; // = 1/1024
439 
440  // upper threshold in lifting (nonzero matrix coefficients with larger absolute value will be reformulated)
441  _realParamName[SoPlex::LIFTMAXVAL] = "liftmaxval";
442  _realParamDescription[SoPlex::LIFTMAXVAL] = "lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated)";
446 
447  // threshold for using sparse pricing (no. of violations need to be smaller than threshold * dimension of problem)
448  _realParamName[SoPlex::SPARSITY_THRESHOLD] = "sparsity_threshold";
449  _realParamDescription[SoPlex::SPARSITY_THRESHOLD] = "sparse pricing threshold (#violations < dimension * SPARSITY_THRESHOLD activates sparse pricing)";
453 
454  // threshold on number of rows vs. number of columns for switching from column to row representations in auto mode
455  _realParamName[SoPlex::REPRESENTATION_SWITCH] = "representation_switch";
456  _realParamDescription[SoPlex::REPRESENTATION_SWITCH] = "threshold on number of rows vs. number of columns for switching from column to row representations in auto mode";
460 
461  // geometric frequency at which to apply rational reconstruction
462  _realParamName[SoPlex::RATREC_FREQ] = "ratrec_freq";
463  _realParamDescription[SoPlex::RATREC_FREQ] = "geometric frequency at which to apply rational reconstruction";
467 
468  // minimal reduction (sum of removed rows/cols) to continue simplification
469  _realParamName[SoPlex::MINRED] = "minred";
470  _realParamDescription[SoPlex::MINRED] = "minimal reduction (sum of removed rows/cols) to continue simplification";
474 
476  }
477 
478  for( int i = 0; i < SoPlex::BOOLPARAM_COUNT; i++ )
480 
481  for( int i = 0; i < SoPlex::INTPARAM_COUNT; i++ )
483 
484  for( int i = 0; i < SoPlex::REALPARAM_COUNT; i++ )
486 
487 #ifdef SOPLEX_WITH_RATIONALPARAM
488  for( int i = 0; i < SoPlex::RATIONALPARAM_COUNT; i++ )
489  _rationalParamValues[i] = _rationalParamDefault[i];
490 #endif
491  }
492 
493  /// copy constructor
495  {
496  *this = settings;
497  }
498 
499  /// assignment operator
501  {
502  for( int i = 0; i < SoPlex::BOOLPARAM_COUNT; i++ )
503  _boolParamValues[i] = settings._boolParamValues[i];
504 
505  for( int i = 0; i < SoPlex::INTPARAM_COUNT; i++ )
506  _intParamValues[i] = settings._intParamValues[i];
507 
508  for( int i = 0; i < SoPlex::REALPARAM_COUNT; i++ )
509  _realParamValues[i] = settings._realParamValues[i];
510 
511 #ifdef SOPLEX_WITH_RATIONALPARAM
512  for( int i = 0; i < SoPlex::RATIONALPARAM_COUNT; i++ )
513  _rationalParamValues[i] = settings._rationalParamValues[i];
514 #endif
515 
516  return *this;
517  }
518  };
519 
520 
521 
523 
524 
525 
529 
530 
531 
537 
538 
539 
545 
546 
547 
548 #ifdef SOPLEX_WITH_RATIONALPARAM
549  std::string SoPlex::Settings::_rationalParamName[SoPlex::RATIONALPARAM_COUNT];
550  std::string SoPlex::Settings::_rationalParamDescription[SoPlex::RATIONALPARAM_COUNT];
551  Rational SoPlex::Settings::_rationalParamLower[SoPlex::RATIONALPARAM_COUNT];
552  Rational SoPlex::Settings::_rationalParamUpper[SoPlex::RATIONALPARAM_COUNT];
553  Rational SoPlex::Settings::_rationalParamDefault[SoPlex::RATIONALPARAM_COUNT];
554 #endif
555 
556 
557 
558  /// default constructor
560  : _statistics(0)
561  , _currentSettings(0)
562  , _scalerUniequi(false)
563  , _scalerBiequi(true)
564  , _scalerGeo1(1)
565  , _scalerGeo8(8)
566  , _simplifier(0)
567  , _scaler(0)
568  , _starter(0)
569  , _rationalLP(0)
570  , _unitMatrixRational(0)
571  , _status(SPxSolver::UNKNOWN)
572  , _hasBasis(false)
573  , _hasSolReal(false)
574  , _hasSolRational(false)
575  {
576  // transfer message handler
582 
583  // give lu factorization to solver
585 
586  // the real LP is initially stored in the solver; the rational LP is constructed, when the parameter SYNCMODE is
587  // initialized in setSettings() below
588  _realLP = &_solver;
589  _isRealLPLoaded = true;
591 
592  // initialize statistics
595 
596  // initialize parameter settings to default
599  setSettings(*_currentSettings, true, true);
600 
602 
603  assert(_isConsistent());
604  }
605 
606 
607 
608  /// assignment operator
610  {
611  if( this != &rhs )
612  {
613  // copy message handler
614  spxout = rhs.spxout;
615 
616  // copy statistics
617  *_statistics = *(rhs._statistics);
618 
619  // copy settings
621 
622  // copy solver components
623  _solver = rhs._solver;
624  _slufactor = rhs._slufactor;
628  _scalerGeo1 = rhs._scalerGeo1;
629  _scalerGeo8 = rhs._scalerGeo8;
631  _starterSum = rhs._starterSum;
633  _pricerAuto = rhs._pricerAuto;
643 
644  // copy solution data
645  _status = rhs._status;
649 
650  if( rhs._hasSolReal )
651  _solReal = rhs._solReal;
652 
653  if( rhs._hasSolRational )
655 
656  // set message handlers in members
662 
663  // transfer the lu solver
665 
666  // initialize pointers for simplifier, scaler, and starter
670 
671  // copy real LP if different from the LP in the solver
672  if( rhs._realLP != &(rhs._solver) )
673  {
674  _realLP = 0;
676  _realLP = new (_realLP) SPxLPReal(*(rhs._realLP));
677  }
678  else
679  _realLP = &_solver;
680 
681  // copy rational LP
682  if( rhs._rationalLP == 0 )
683  {
685  _rationalLP = 0;
686  }
687  else
688  {
690  _rationalLP = 0;
693  }
694 
695  // copy boolean flags
697  _hasSolReal = rhs._hasSolReal;
699  _hasBasis = rhs._hasBasis;
700  }
701 
702  assert(_isConsistent());
703 
704  return *this;
705  }
706 
707 
708 
709  /// copy constructor
710  ///@todo improve performance by implementing a separate copy constructor
711  SoPlex::SoPlex(const SoPlex& rhs)
712  {
713  // allocate memory as in default constructor
714  _statistics = 0;
717 
718  _currentSettings = 0;
721 
722  // call assignment operator
723  *this = rhs;
724  }
725 
726 
727 
728  /// destructor
730  {
731  assert(_isConsistent());
732 
733  // free settings
734  _currentSettings->~Settings();
736 
737  // free statistics
740 
741  // free real LP if different from the LP in the solver
742  assert(_realLP != 0);
743  if( _realLP != &_solver )
744  {
745  _realLP->~SPxLPReal();
746  spx_free(_realLP);
747  }
748 
749  // free rational LP
750  if( _rationalLP != 0 )
751  {
752  _rationalLP->~SPxLPRational();
754  }
755 
756  // free unit vectors
757  for( int i = 0; i < _unitMatrixRational.size(); i++ )
758  {
759  if( _unitMatrixRational[i] != 0 )
760  {
761  _unitMatrixRational[i]->~UnitVectorRational();
763  }
764  }
765  }
766 
767 
768 
769  /// returns number of rows
771  {
772  assert(_realLP != 0);
773  return _realLP->nRows();
774  }
775 
776 
777 
778  /// returns number of columns
780  {
781  assert(_realLP != 0);
782  return _realLP->nCols();
783  }
784 
785 
786 
787  /// returns number of nonzeros
789  {
790  assert(_realLP != 0);
791  return _realLP->nNzos();
792  }
793 
794 
795 
796  /// returns smallest non-zero element in absolute value
798  {
799  assert(_realLP != 0);
800  return _realLP->minAbsNzo();
801  }
802 
803 
804 
805  /// returns biggest non-zero element in absolute value
807  {
808  assert(_realLP != 0);
809  return _realLP->maxAbsNzo();
810  }
811 
812 
813 
814  /// gets row \p i
815  void SoPlex::getRowReal(int i, LPRowReal& lprow) const
816  {
817  assert(_realLP != 0);
818  _realLP->getRow(i, lprow);
819  }
820 
821 
822 
823  /// gets rows \p start, ..., \p end.
824  void SoPlex::getRowsReal(int start, int end, LPRowSetReal& lprowset) const
825  {
826  assert(_realLP != 0);
827  _realLP->getRows(start, end, lprowset);
828  }
829 
830 
831 
832  /// returns vector of row \p i
833  const SVectorReal& SoPlex::rowVectorReal(int i) const
834  {
835  assert(_realLP != 0);
836  return _realLP->rowVector(i);
837  }
838 
839 
840 
841  /// returns right-hand side vector
843  {
844  assert(_realLP != 0);
845  return _realLP->rhs();
846  }
847 
848 
849 
850  /// returns right-hand side of row \p i
851  Real SoPlex::rhsReal(int i) const
852  {
853  assert(_realLP != 0);
854  return _realLP->rhs(i);
855  }
856 
857 
858 
859  /// returns left-hand side vector
861  {
862  assert(_realLP != 0);
863  return _realLP->lhs();
864  }
865 
866 
867 
868  /// returns left-hand side of row \p i
869  Real SoPlex::lhsReal(int i) const
870  {
871  assert(_realLP != 0);
872  return _realLP->lhs(i);
873  }
874 
875 
876 
877  /// returns inequality type of row \p i
879  {
880  assert(_realLP != 0);
881  return _realLP->rowType(i);
882  }
883 
884 
885 
886  /// gets column \p i
887  void SoPlex::getColReal(int i, LPColReal& lpcol) const
888  {
889  assert(_realLP != 0);
890  return _realLP->getCol(i, lpcol);
891  }
892 
893 
894 
895  /// gets columns \p start, ..., \p end
896  void SoPlex::getColsReal(int start, int end, LPColSetReal& lpcolset) const
897  {
898  assert(_realLP != 0);
899  return _realLP->getCols(start, end, lpcolset);
900  }
901 
902 
903 
904  /// returns vector of column \p i
905  const SVectorReal& SoPlex::colVectorReal(int i) const
906  {
907  assert(_realLP != 0);
908  return _realLP->colVector(i);
909  }
910 
911 
912 
913  /// returns upper bound vector
915  {
916  assert(_realLP != 0);
917  return _realLP->upper();
918  }
919 
920 
921 
922  /// returns upper bound of column \p i
923  Real SoPlex::upperReal(int i) const
924  {
925  assert(_realLP != 0);
926  return _realLP->upper(i);
927  }
928 
929 
930 
931  /// returns lower bound vector
933  {
934  assert(_realLP != 0);
935  return _realLP->lower();
936  }
937 
938 
939 
940  /// returns lower bound of column \p i
941  Real SoPlex::lowerReal(int i) const
942  {
943  assert(_realLP != 0);
944  return _realLP->lower(i);
945  }
946 
947 
948 
949  /// gets objective function vector
951  {
952  assert(_realLP != 0);
953  _realLP->getObj(obj);
954  }
955 
956 
957 
958  /// returns objective value of column \p i
959  Real SoPlex::objReal(int i) const
960  {
961  assert(_realLP != 0);
962  return _realLP->obj(i);
963  }
964 
965 
966 
967  /// returns objective function vector after transformation to a maximization problem; since this is how it is stored
968  /// internally, this is generally faster
970  {
971  assert(_realLP != 0);
972  return _realLP->maxObj();
973  }
974 
975 
976 
977  /// returns objective value of column \p i after transformation to a maximization problem; since this is how it is
978  /// stored internally, this is generally faster
980  {
981  assert(_realLP != 0);
982  return _realLP->maxObj(i);
983  }
984 
985 
986 
987  /// gets number of available dual norms
988  void SoPlex::getNdualNorms(int& nnormsRow, int& nnormsCol) const
989  {
990  _solver.getNdualNorms(nnormsRow, nnormsCol);
991  }
992 
993 
994 
995  /// gets steepest edge norms and returns false if they are not available
996  bool SoPlex::getDualNorms(int& nnormsRow, int& nnormsCol, Real* norms) const
997  {
998  return _solver.getDualNorms(nnormsRow, nnormsCol, norms);
999  }
1000 
1001 
1002 
1003  /// sets steepest edge norms and returns false if that's not possible
1004  bool SoPlex::setDualNorms(int nnormsRow, int nnormsCol, Real* norms)
1005  {
1006  return _solver.setDualNorms(nnormsRow, nnormsCol, norms);
1007  }
1008 
1009 
1010 
1011  /// returns number of rows
1013  {
1014  assert(_rationalLP != 0);
1015  return _rationalLP->nRows();
1016  }
1017 
1018 
1019 
1020  /// returns number of columns
1022  {
1023  assert(_rationalLP != 0);
1024  return _rationalLP->nCols();
1025  }
1026 
1027 
1028 
1029  /// returns number of nonzeros
1031  {
1032  assert(_rationalLP != 0);
1033  return _rationalLP->nNzos();
1034  }
1035 
1036 
1037 
1038  /// returns smallest non-zero element in absolute value
1040  {
1041  assert(_rationalLP != 0);
1042  return _rationalLP->minAbsNzo();
1043  }
1044 
1045 
1046 
1047  /// returns biggest non-zero element in absolute value
1049  {
1050  assert(_rationalLP != 0);
1051  return _rationalLP->maxAbsNzo();
1052  }
1053 
1054 
1055 
1056  /// gets row \p i
1057  void SoPlex::getRowRational(int i, LPRowRational& lprow) const
1058  {
1059  assert(_rationalLP != 0);
1060  _rationalLP->getRow(i, lprow);
1061  }
1062 
1063 
1064 
1065  /// gets rows \p start, ..., \p end.
1066  void SoPlex::getRowsRational(int start, int end, LPRowSetRational& lprowset) const
1067  {
1068  assert(_rationalLP != 0);
1069  _rationalLP->getRows(start, end, lprowset);
1070  }
1071 
1072 
1073 
1074  /// returns vector of row \p i
1076  {
1077  assert(_rationalLP != 0);
1078  return _rationalLP->rowVector(i);
1079  }
1080 
1081 
1082 
1083  /// returns right-hand side vector
1085  {
1086  assert(_rationalLP != 0);
1087  return _rationalLP->rhs();
1088  }
1089 
1090 
1091 
1092  /// returns right-hand side of row \p i
1093  const Rational& SoPlex::rhsRational(int i) const
1094  {
1095  assert(_rationalLP != 0);
1096  return _rationalLP->rhs(i);
1097  }
1098 
1099 
1100 
1101  /// returns left-hand side vector
1103  {
1104  assert(_rationalLP != 0);
1105  return _rationalLP->lhs();
1106  }
1107 
1108 
1109 
1110  /// returns left-hand side of row \p i
1111  const Rational& SoPlex::lhsRational(int i) const
1112  {
1113  assert(_rationalLP != 0);
1114  return _rationalLP->lhs(i);
1115  }
1116 
1117 
1118 
1119  /// returns inequality type of row \p i
1121  {
1122  assert(_rationalLP != 0);
1123  return _rationalLP->rowType(i);
1124  }
1125 
1126 
1127 
1128  /// gets column \p i
1129  void SoPlex::getColRational(int i, LPColRational& lpcol) const
1130  {
1131  assert(_rationalLP != 0);
1132  return _rationalLP->getCol(i, lpcol);
1133  }
1134 
1135 
1136 
1137  /// gets columns \p start, ..., \p end
1138  void SoPlex::getColsRational(int start, int end, LPColSetRational& lpcolset) const
1139  {
1140  assert(_rationalLP != 0);
1141  return _rationalLP->getCols(start, end, lpcolset);
1142  }
1143 
1144 
1145 
1146  /// returns vector of column \p i
1148  {
1149  assert(_rationalLP != 0);
1150  return _rationalLP->colVector(i);
1151  }
1152 
1153 
1154 
1155  /// returns upper bound vector
1157  {
1158  assert(_rationalLP != 0);
1159  return _rationalLP->upper();
1160  }
1161 
1162 
1163 
1164  /// returns upper bound of column \p i
1165  const Rational& SoPlex::upperRational(int i) const
1166  {
1167  assert(_rationalLP != 0);
1168  return _rationalLP->upper(i);
1169  }
1170 
1171 
1172 
1173  /// returns lower bound vector
1175  {
1176  assert(_rationalLP != 0);
1177  return _rationalLP->lower();
1178  }
1179 
1180 
1181 
1182  /// returns lower bound of column \p i
1183  const Rational& SoPlex::lowerRational(int i) const
1184  {
1185  assert(_rationalLP != 0);
1186  return _rationalLP->lower(i);
1187  }
1188 
1189 
1190 
1191  /// gets objective function vector
1193  {
1194  assert(_rationalLP != 0);
1195  _rationalLP->getObj(obj);
1196  }
1197 
1198 
1199 
1200  /// gets objective value of column \p i
1201  void SoPlex::getObjRational(int i, Rational& obj) const
1202  {
1203  obj = maxObjRational(i);
1205  obj *= -1;
1206  }
1207 
1208 
1209 
1210  /// returns objective value of column \p i
1212  {
1213  assert(_rationalLP != 0);
1214  return _rationalLP->obj(i);
1215  }
1216 
1217 
1218 
1219  /// returns objective function vector after transformation to a maximization problem; since this is how it is stored
1220  /// internally, this is generally faster
1222  {
1223  assert(_rationalLP != 0);
1224  return _rationalLP->maxObj();
1225  }
1226 
1227 
1228 
1229  /// returns objective value of column \p i after transformation to a maximization problem; since this is how it is
1230  /// stored internally, this is generally faster
1231  const Rational& SoPlex::maxObjRational(int i) const
1232  {
1233  assert(_rationalLP != 0);
1234  return _rationalLP->maxObj(i);
1235  }
1236 
1237 
1238 
1239  /// adds a single row
1240  void SoPlex::addRowReal(const LPRowReal& lprow)
1241  {
1242  assert(_realLP != 0);
1243 
1244  _addRowReal(lprow);
1245 
1247  {
1248  _rationalLP->addRow(lprow);
1249  _rowTypes.append(_rangeTypeReal(lprow.lhs(), lprow.rhs()));
1250  }
1251 
1253  }
1254 
1255 
1256 
1257  /// adds multiple rows
1258  void SoPlex::addRowsReal(const LPRowSetReal& lprowset)
1259  {
1260  assert(_realLP != 0);
1261 
1262  _addRowsReal(lprowset);
1263 
1265  {
1266  _rationalLP->addRows(lprowset);
1267  for( int i = 0; i < lprowset.num(); i++ )
1268  _rowTypes.append(_rangeTypeReal(lprowset.lhs(i), lprowset.rhs(i)));
1269  }
1270 
1272  }
1273 
1274 
1275 
1276  /// adds a single column
1277  void SoPlex::addColReal(const LPColReal& lpcol)
1278  {
1279  assert(_realLP != 0);
1280 
1281  _addColReal(lpcol);
1282 
1284  {
1285  _rationalLP->addCol(lpcol);
1286  _colTypes.append(_rangeTypeReal(lpcol.lower(), lpcol.upper()));
1287  }
1288 
1290  }
1291 
1292 
1293 
1294  /// adds multiple columns
1295  void SoPlex::addColsReal(const LPColSetReal& lpcolset)
1296  {
1297  assert(_realLP != 0);
1298 
1299  _addColsReal(lpcolset);
1300 
1302  {
1303  _rationalLP->addCols(lpcolset);
1304  for( int i = 0; i < lpcolset.num(); i++ )
1305  _colTypes.append(_rangeTypeReal(lpcolset.lower(i), lpcolset.upper(i)));
1306  }
1307 
1309  }
1310 
1311 
1312 
1313  /// replaces row \p i with \p lprow
1314  void SoPlex::changeRowReal(int i, const LPRowReal& lprow)
1315  {
1316  assert(_realLP != 0);
1317 
1318  _changeRowReal(i, lprow);
1319 
1321  {
1322  _rationalLP->changeRow(i, lprow);
1323  _rowTypes[i] = _rangeTypeReal(lprow.lhs(), lprow.rhs());
1324  }
1325 
1327  }
1328 
1329 
1330 
1331  /// changes left-hand side vector for constraints to \p lhs
1333  {
1334  assert(_realLP != 0);
1335 
1336  _changeLhsReal(lhs);
1337 
1339  {
1341  for( int i = 0; i < numRowsRational(); i++ )
1343  }
1344 
1346  }
1347 
1348 
1349 
1350  /// changes left-hand side of row \p i to \p lhs
1351  void SoPlex::changeLhsReal(int i, const Real& lhs)
1352  {
1353  assert(_realLP != 0);
1354 
1355  _changeLhsReal(i, lhs);
1356 
1358  {
1359  _rationalLP->changeLhs(i, lhs);
1361  }
1362 
1364  }
1365 
1366 
1367 
1368  /// changes right-hand side vector to \p rhs
1370  {
1371  assert(_realLP != 0);
1372 
1373  _changeRhsReal(rhs);
1374 
1376  {
1378  for( int i = 0; i < numRowsRational(); i++ )
1380  }
1381 
1383  }
1384 
1385 
1386 
1387  /// changes right-hand side of row \p i to \p rhs
1388  void SoPlex::changeRhsReal(int i, const Real& rhs)
1389  {
1390  assert(_realLP != 0);
1391 
1392  _changeRhsReal(i, rhs);
1393 
1395  {
1396  _rationalLP->changeRhs(i, rhs);
1398  }
1399 
1401  }
1402 
1403 
1404 
1405  /// changes left- and right-hand side vectors
1406  void SoPlex::changeRangeReal(const VectorReal& lhs, const VectorReal& rhs)
1407  {
1408  assert(_realLP != 0);
1409 
1410  _changeRangeReal(lhs, rhs);
1411 
1413  {
1415  for( int i = 0; i < numRowsRational(); i++ )
1416  _rowTypes[i] = _rangeTypeReal(lhs[i], rhs[i]);
1417  }
1418 
1420  }
1421 
1422 
1423 
1424  /// changes left- and right-hand side of row \p i
1425  void SoPlex::changeRangeReal(int i, const Real& lhs, const Real& rhs)
1426  {
1427  assert(_realLP != 0);
1428 
1429  _changeRangeReal(i,lhs, rhs);
1430 
1432  {
1433  _rationalLP->changeRange(i, lhs, rhs);
1434  _rowTypes[i] = _rangeTypeReal(lhs, rhs);
1435  }
1436 
1438  }
1439 
1440 
1441 
1442  /// replaces column \p i with \p lpcol
1443  void SoPlex::changeColReal(int i, const LPColReal& lpcol)
1444  {
1445  assert(_realLP != 0);
1446 
1447  _changeColReal(i, lpcol);
1448 
1450  {
1451  _rationalLP->changeCol(i, lpcol);
1452  _colTypes[i] = _rangeTypeReal(lpcol.lower(), lpcol.upper());
1453  }
1454 
1456  }
1457 
1458 
1459 
1460  /// changes vector of lower bounds to \p lower
1462  {
1463  assert(_realLP != 0);
1464 
1465  _changeLowerReal(lower);
1466 
1468  {
1470  for( int i = 0; i < numColsRational(); i++ )
1472  }
1473 
1474 
1476  }
1477 
1478 
1479 
1480  /// changes lower bound of column i to \p lower
1481  void SoPlex::changeLowerReal(int i, const Real& lower)
1482  {
1483  assert(_realLP != 0);
1484 
1485  _changeLowerReal(i, lower);
1486 
1488  {
1489  _rationalLP->changeLower(i, lower);
1491  }
1492 
1494  }
1495 
1496 
1497 
1498  /// changes vector of upper bounds to \p upper
1500  {
1501  assert(_realLP != 0);
1502 
1503  _changeUpperReal(upper);
1504 
1506  {
1508  for( int i = 0; i < numColsRational(); i++ )
1510  }
1511 
1513  }
1514 
1515 
1516 
1517  /// changes \p i 'th upper bound to \p upper
1518  void SoPlex::changeUpperReal(int i, const Real& upper)
1519  {
1520  assert(_realLP != 0);
1521 
1522  _changeUpperReal(i, upper);
1523 
1525  {
1526  _rationalLP->changeUpper(i, upper);
1528  }
1529 
1531  }
1532 
1533 
1534 
1535  /// changes vectors of column bounds to \p lower and \p upper
1536  void SoPlex::changeBoundsReal(const VectorReal& lower, const VectorReal& upper)
1537  {
1538  assert(_realLP != 0);
1539 
1540  _changeBoundsReal(lower, upper);
1541 
1543  {
1545  for( int i = 0; i < numColsRational(); i++ )
1546  _colTypes[i] = _rangeTypeReal(lower[i], upper[i]);
1547  }
1548 
1550  }
1551 
1552 
1553 
1554  /// changes bounds of column \p i to \p lower and \p upper
1555  void SoPlex::changeBoundsReal(int i, const Real& lower, const Real& upper)
1556  {
1557  assert(_realLP != 0);
1558 
1559  _changeBoundsReal(i, lower, upper);
1560 
1562  {
1563  _rationalLP->changeBounds(i, lower, upper);
1564  _colTypes[i] = _rangeTypeReal(lower, upper);
1565  }
1567  }
1568 
1569 
1570 
1571  /// changes objective function vector to \p obj
1573  {
1574  assert(_realLP != 0);
1575 
1576  _realLP->changeObj(obj);
1577 
1580 
1582  }
1583 
1584 
1585 
1586  /// changes objective coefficient of column i to \p obj
1587  void SoPlex::changeObjReal(int i, const Real& obj)
1588  {
1589  assert(_realLP != 0);
1590 
1591  _realLP->changeObj(i, obj);
1592 
1594  _rationalLP->changeObj(i, obj);
1595 
1597  }
1598 
1599 
1600 
1601  /// changes matrix entry in row \p i and column \p j to \p val
1602  void SoPlex::changeElementReal(int i, int j, const Real& val)
1603  {
1604  assert(_realLP != 0);
1605 
1606  _changeElementReal(i, j, val);
1607 
1609  _rationalLP->changeElement(i, j, val);
1610 
1612  }
1613 
1614 
1615 
1616  /// removes row \p i
1618  {
1619  assert(_realLP != 0);
1620 
1621  _removeRowReal(i);
1622 
1624  {
1625  _rationalLP->removeRow(i);
1628  assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i)));
1629  }
1630 
1632  }
1633 
1634 
1635 
1636  /// removes all rows with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the
1637  /// new index where row \p i has been moved to; note that \p perm must point to an array of size at least
1638  /// #numRowsReal()
1639  void SoPlex::removeRowsReal(int perm[])
1640  {
1641  assert(_realLP != 0);
1642 
1643  const int oldsize = numRowsReal();
1644  _removeRowsReal(perm);
1645 
1647  {
1648  _rationalLP->removeRows(perm);
1649  for( int i = 0; i < oldsize; i++ )
1650  {
1651  if( perm[i] >= 0 )
1652  _rowTypes[perm[i]] = _rowTypes[i];
1653  }
1655  for( int i = 0; i < numRowsRational(); i++ )
1656  {
1657  assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i)));
1658  }
1659  }
1660 
1662  }
1663 
1664 
1665 
1666  /// remove all rows with indices in array \p idx of size \p n; an array \p perm of size #numRowsReal() may be passed
1667  /// as buffer memory
1668  void SoPlex::removeRowsReal(int idx[], int n, int perm[])
1669  {
1670  if( perm == 0 )
1671  {
1673  _idxToPerm(idx, n, p.get_ptr(), numRowsReal());
1675  }
1676  else
1677  {
1678  _idxToPerm(idx, n, perm, numRowsReal());
1679  SoPlex::removeRowsReal(perm);
1680  }
1681  }
1682 
1683 
1684 
1685  /// removes rows \p start to \p end including both; an array \p perm of size #numRowsReal() may be passed as buffer
1686  /// memory
1687  void SoPlex::removeRowRangeReal(int start, int end, int perm[])
1688  {
1689  if( perm == 0 )
1690  {
1692  _rangeToPerm(start, end, p.get_ptr(), numRowsReal());
1694  }
1695  else
1696  {
1697  _rangeToPerm(start, end, perm, numRowsReal());
1698  SoPlex::removeRowsReal(perm);
1699  }
1700  }
1701 
1702 
1703 
1704  /// removes column i
1706  {
1707  assert(_realLP != 0);
1708 
1709  _removeColReal(i);
1710 
1712  {
1713  _rationalLP->removeCol(i);
1717  }
1718 
1720  }
1721 
1722 
1723 
1724  /// removes all columns with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the
1725  /// new index where column \p i has been moved to; note that \p perm must point to an array of size at least
1726  /// #numColsReal()
1727  void SoPlex::removeColsReal(int perm[])
1728  {
1729  assert(_realLP != 0);
1730 
1731  const int oldsize = numColsReal();
1732  _removeColsReal(perm);
1733 
1735  {
1736  _rationalLP->removeCols(perm);
1737  for( int i = 0; i < oldsize; i++ )
1738  {
1739  if( perm[i] >= 0 )
1740  _colTypes[perm[i]] = _colTypes[i];
1741  }
1743  for( int i = 0; i < numColsRational(); i++ )
1744  {
1746  }
1747  }
1748 
1750  }
1751 
1752 
1753 
1754  /// remove all columns with indices in array \p idx of size \p n; an array \p perm of size #numColsReal() may be
1755  /// passed as buffer memory
1756  void SoPlex::removeColsReal(int idx[], int n, int perm[])
1757  {
1758  if( perm == 0 )
1759  {
1761  _idxToPerm(idx, n, p.get_ptr(), numColsReal());
1763  }
1764  else
1765  {
1766  _idxToPerm(idx, n, perm, numColsReal());
1767  SoPlex::removeColsReal(perm);
1768  }
1769  }
1770 
1771 
1772 
1773  /// removes columns \p start to \p end including both; an array \p perm of size #numColsReal() may be passed as
1774  /// buffer memory
1775  void SoPlex::removeColRangeReal(int start, int end, int perm[])
1776  {
1777  if( perm == 0 )
1778  {
1780  _rangeToPerm(start, end, p.get_ptr(), numColsReal());
1782  }
1783  else
1784  {
1785  _rangeToPerm(start, end, perm, numColsReal());
1786  SoPlex::removeColsReal(perm);
1787  }
1788  }
1789 
1790 
1791 
1792  /// clears the LP
1794  {
1795  assert(_realLP != 0);
1796 
1797  _realLP->clear();
1798  _hasBasis = false;
1799 
1801  {
1802  _rationalLP->clear();
1803  _rowTypes.clear();
1804  _colTypes.clear();
1805  }
1806 
1808  }
1809 
1810 
1811 
1812  /// synchronizes real LP with rational LP, i.e., copies (rounded) rational LP into real LP, if sync mode is manual
1814  {
1815  assert(_isConsistent());
1816 
1818  _syncLPReal();
1819  }
1820 
1821 
1822 
1823  /// adds a single row
1825  {
1826  assert(_rationalLP != 0);
1827 
1829  return;
1830 
1831  _rationalLP->addRow(lprow);
1832  _rowTypes.append(_rangeTypeRational(lprow.lhs(), lprow.rhs()));
1833 
1835  _addRowReal(lprow);
1836 
1838  }
1839 
1840 
1841 
1842 #ifdef SOPLEX_WITH_GMP
1843  /// adds a single row
1844  void SoPlex::addRowRational(const mpq_t* lhs, const mpq_t* rowValues, const int* rowIndices, const int rowSize, const mpq_t* rhs)
1845  {
1846  assert(_rationalLP != 0);
1847 
1849  return;
1850 
1851  _rationalLP->addRow(lhs, rowValues, rowIndices, rowSize, rhs);
1852  int i = numRowsRational() - 1;
1854 
1857 
1859  }
1860 
1861 
1862 
1863  /// adds a set of rows
1864  void SoPlex::addRowsRational(const mpq_t* lhs, const mpq_t* rowValues, const int* rowIndices, const int* rowStarts, const int* rowLengths, const int numRows, const int numValues, const mpq_t* rhs)
1865  {
1866  assert(_rationalLP != 0);
1867 
1869  return;
1870 
1871  _rationalLP->addRows(lhs, rowValues, rowIndices, rowStarts, rowLengths, numRows, numValues, rhs);
1872  for( int i = numRowsRational() - numRows; i < numRowsRational(); i++ )
1874 
1876  {
1877  LPRowSetReal lprowset;
1878  for( int i = numRowsRational() - numRows; i < numRowsRational(); i++ )
1880  _addRowsReal(lprowset);
1881  }
1882 
1884  }
1885 #endif
1886 
1887 
1888 
1889  /// adds multiple rows
1891  {
1892  assert(_rationalLP != 0);
1893 
1895  return;
1896 
1897  _rationalLP->addRows(lprowset);
1898  for( int i = 0; i < lprowset.num(); i++ )
1899  _rowTypes.append(_rangeTypeRational(lprowset.lhs(i), lprowset.rhs(i)));
1900 
1902  _addRowsReal(lprowset);
1903 
1905  }
1906 
1907 
1908 
1909  /// adds a single column
1911  {
1912  assert(_rationalLP != 0);
1913 
1915  return;
1916 
1917  _rationalLP->addCol(lpcol);
1918  _colTypes.append(_rangeTypeRational(lpcol.lower(), lpcol.upper()));
1919 
1921  _addColReal(lpcol);
1922 
1924  }
1925 
1926 
1927 
1928 #ifdef SOPLEX_WITH_GMP
1929  /// adds a single column
1930  void SoPlex::addColRational(const mpq_t* obj, const mpq_t* lower, const mpq_t* colValues, const int* colIndices, const int colSize, const mpq_t* upper)
1931  {
1932  assert(_rationalLP != 0);
1933 
1935  return;
1936 
1937  _rationalLP->addCol(obj, lower, colValues, colIndices, colSize, upper);
1938  int i = numColsRational() - 1;
1940 
1944 
1946  }
1947 
1948 
1949 
1950  /// adds a set of columns
1951  void SoPlex::addColsRational(const mpq_t* obj, const mpq_t* lower, const mpq_t* colValues, const int* colIndices, const int* colStarts, const int* colLengths, const int numCols, const int numValues, const mpq_t* upper)
1952  {
1953  assert(_rationalLP != 0);
1954 
1956  return;
1957 
1958  _rationalLP->addCols(obj, lower, colValues, colIndices, colStarts, colLengths, numCols, numValues, upper);
1959  for( int i = numColsRational() - numCols; i < numColsRational(); i++ )
1961 
1963  {
1964  LPColSetReal lpcolset;
1965  for( int i = numColsRational() - numCols; i < numColsRational(); i++ )
1966  lpcolset.add(Real(maxObjRational(i)) * (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE ? 1.0 : -1.0),
1968  _addColsReal(lpcolset);
1969  }
1970 
1972  }
1973 #endif
1974 
1975 
1976 
1977  /// adds multiple columns
1979  {
1980  assert(_rationalLP != 0);
1981 
1983  return;
1984 
1985  _rationalLP->addCols(lpcolset);
1986  for( int i = 0; i < lpcolset.num(); i++ )
1987  _colTypes.append(_rangeTypeRational(lpcolset.lower(i), lpcolset.upper(i)));
1988 
1990  _addColsReal(lpcolset);
1991 
1993  }
1994 
1995 
1996 
1997  /// replaces row \p i with \p lprow
1998  void SoPlex::changeRowRational(int i, const LPRowRational& lprow)
1999  {
2000  assert(_rationalLP != 0);
2001 
2003  return;
2004 
2005  _rationalLP->changeRow(i, lprow);
2006  _rowTypes[i] = _rangeTypeRational(lprow.lhs(), lprow.rhs());
2007 
2009  _changeRowReal(i, lprow);
2010 
2012  }
2013 
2014 
2015 
2016  /// changes left-hand side vector for constraints to \p lhs
2018  {
2019  assert(_rationalLP != 0);
2020 
2022  return;
2023 
2024  _rationalLP->changeLhs(lhs);
2025  for( int i = 0; i < numRowsRational(); i++ )
2026  _rowTypes[i] = _rangeTypeRational(lhs[i], _rationalLP->rhs(i));
2027 
2030 
2032  }
2033 
2034 
2035 
2036  /// changes left-hand side of row \p i to \p lhs
2037  void SoPlex::changeLhsRational(int i, const Rational& lhs)
2038  {
2039  assert(_rationalLP != 0);
2040 
2042  return;
2043 
2044  _rationalLP->changeLhs(i, lhs);
2046 
2048  _changeLhsReal(i, Real(lhs));
2049 
2051  }
2052 
2053 
2054 
2055 #ifdef SOPLEX_WITH_GMP
2056  /// changes left-hand side of row \p i to \p lhs
2057  void SoPlex::changeLhsRational(int i, const mpq_t* lhs)
2058  {
2059  assert(_rationalLP != 0);
2060 
2062  return;
2063 
2064  _rationalLP->changeLhs(i, lhs);
2066 
2069 
2071  }
2072 #endif
2073 
2074 
2075 
2076  /// changes right-hand side vector to \p rhs
2078  {
2079  assert(_rationalLP != 0);
2080 
2082  return;
2083 
2084  _rationalLP->changeRhs(rhs);
2085  for( int i = 0; i < numRowsRational(); i++ )
2086  _rowTypes[i] = _rangeTypeRational(_rationalLP->lhs(i), rhs[i]);
2087 
2090 
2092  }
2093 
2094 
2095 
2096 #ifdef SOPLEX_WITH_GMP
2097  /// changes right-hand side vector to \p rhs
2098  void SoPlex::changeRhsRational(const mpq_t* rhs, int rhsSize)
2099  {
2100  assert(_rationalLP != 0);
2101 
2103  return;
2104 
2105  for( int i = 0; i < rhsSize; i++ )
2106  {
2107  _rationalLP->changeRhs(i, rhs[i]);
2109  }
2110 
2113 
2115  }
2116 #endif
2117 
2118 
2119 
2120  /// changes right-hand side of row \p i to \p rhs
2121  void SoPlex::changeRhsRational(int i, const Rational& rhs)
2122  {
2123  assert(_rationalLP != 0);
2124 
2126  return;
2127 
2128  _rationalLP->changeRhs(i, rhs);
2130 
2132  _changeRhsReal(i, Real(rhs));
2133 
2135  }
2136 
2137 
2138 
2139  /// changes left- and right-hand side vectors
2141  {
2142  assert(_rationalLP != 0);
2143 
2145  return;
2146 
2147  _rationalLP->changeRange(lhs, rhs);
2148  for( int i = 0; i < numRowsRational(); i++ )
2149  _rowTypes[i] = _rangeTypeRational(lhs[i], rhs[i]);
2150 
2153 
2155  }
2156 
2157 
2158 
2159  /// changes left- and right-hand side of row \p i
2160  void SoPlex::changeRangeRational(int i, const Rational& lhs, const Rational& rhs)
2161  {
2162  assert(_rationalLP != 0);
2163 
2165  return;
2166 
2167  _rationalLP->changeRange(i, lhs, rhs);
2168  _rowTypes[i] = _rangeTypeRational(lhs, rhs);
2169 
2171  _changeRangeReal(i, Real(lhs), Real(rhs));
2172 
2174  }
2175 
2176 
2177 
2178 #ifdef SOPLEX_WITH_GMP
2179  /// changes left-hand side of row \p i to \p lhs
2180  void SoPlex::changeRangeRational(int i, const mpq_t* lhs, const mpq_t* rhs)
2181  {
2182  assert(_rationalLP != 0);
2183 
2185  return;
2186 
2187  _rationalLP->changeRange(i, lhs, rhs);
2189 
2192 
2194  }
2195 #endif
2196 
2197 
2198 
2199  /// replaces column \p i with \p lpcol
2200  void SoPlex::changeColRational(int i, const LPColRational& lpcol)
2201  {
2202  assert(_rationalLP != 0);
2203 
2205  return;
2206 
2207  _rationalLP->changeCol(i, lpcol);
2208  _rowTypes[i] = _rangeTypeRational(lpcol.lower(), lpcol.upper());
2209 
2211  _changeColReal(i, lpcol);
2212 
2214  }
2215 
2216 
2217 
2218  /// changes vector of lower bounds to \p lower
2220  {
2221  assert(_rationalLP != 0);
2222 
2224  return;
2225 
2226  _rationalLP->changeLower(lower);
2227  for( int i = 0; i < numColsRational(); i++ )
2228  _colTypes[i] = _rangeTypeRational(lower[i], _rationalLP->upper(i));
2229 
2231  _changeLowerReal(DVectorReal(lower));
2232 
2234  }
2235 
2236 
2237 
2238  /// changes lower bound of column i to \p lower
2239  void SoPlex::changeLowerRational(int i, const Rational& lower)
2240  {
2241  assert(_rationalLP != 0);
2242 
2244  return;
2245 
2246  _rationalLP->changeLower(i, lower);
2247  _colTypes[i] = _rangeTypeRational(lower, _rationalLP->upper(i));
2248 
2250  _changeLowerReal(i, Real(lower));
2251 
2253  }
2254 
2255 
2256 
2257 #ifdef SOPLEX_WITH_GMP
2258  /// changes lower bound of column i to \p lower
2259  void SoPlex::changeLowerRational(int i, const mpq_t* lower)
2260  {
2261  assert(_rationalLP != 0);
2262 
2264  return;
2265 
2266  _rationalLP->changeLower(i, lower);
2268 
2271 
2273  }
2274 #endif
2275 
2276 
2277 
2278  /// changes vector of upper bounds to \p upper
2280  {
2281  assert(_rationalLP != 0);
2282 
2284  return;
2285 
2286  _rationalLP->changeUpper(upper);
2287  for( int i = 0; i < numColsRational(); i++ )
2288  _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), upper[i]);
2289 
2291  _changeUpperReal(DVectorReal(upper));
2292 
2294  }
2295 
2296 
2297 
2298  /// changes \p i 'th upper bound to \p upper
2299  void SoPlex::changeUpperRational(int i, const Rational& upper)
2300  {
2301  assert(_rationalLP != 0);
2302 
2304  return;
2305 
2306  _rationalLP->changeUpper(i, upper);
2307  _colTypes[i] = _rangeTypeRational(_rationalLP->lower(i), upper);
2308 
2310  _changeUpperReal(i, Real(upper));
2311 
2313  }
2314 
2315 
2316 
2317 #ifdef SOPLEX_WITH_GMP
2318  /// changes upper bound of column i to \p upper
2319  void SoPlex::changeUpperRational(int i, const mpq_t* upper)
2320  {
2321  assert(_rationalLP != 0);
2322 
2324  return;
2325 
2326  _rationalLP->changeUpper(i, upper);
2328 
2331 
2333  }
2334 #endif
2335 
2336 
2337 
2338  /// changes vectors of column bounds to \p lower and \p upper
2340  {
2341  assert(_rationalLP != 0);
2342 
2344  return;
2345 
2346  _rationalLP->changeBounds(lower, upper);
2347  for( int i = 0; i < numColsRational(); i++ )
2348  _colTypes[i] = _rangeTypeRational(lower[i], upper[i]);
2349 
2351  _changeBoundsReal(DVectorReal(lower), DVectorReal(upper));
2352 
2354  }
2355 
2356 
2357 
2358  /// changes bounds of column \p i to \p lower and \p upper
2359  void SoPlex::changeBoundsRational(int i, const Rational& lower, const Rational& upper)
2360  {
2361  assert(_rationalLP != 0);
2362 
2364  return;
2365 
2366  _rationalLP->changeBounds(i, lower, upper);
2367  _colTypes[i] = _rangeTypeRational(lower, upper);
2368 
2370  _changeBoundsReal(i, Real(lower), Real(upper));
2371 
2373  }
2374 
2375 
2376 
2377 #ifdef SOPLEX_WITH_GMP
2378  /// changes bounds of column \p i to \p lower and \p upper
2379  void SoPlex::changeBoundsRational(int i, const mpq_t* lower, const mpq_t* upper)
2380  {
2381  assert(_rationalLP != 0);
2382 
2384  return;
2385 
2386  _rationalLP->changeBounds(i, lower, upper);
2388 
2391 
2393  }
2394 #endif
2395 
2396 
2397 
2398  /// changes objective function vector to \p obj
2400  {
2401  assert(_rationalLP != 0);
2402 
2404  return;
2405 
2406  _rationalLP->changeObj(obj);
2407 
2409  _realLP->changeObj(DVectorReal(obj));
2410 
2412  }
2413 
2414 
2415 
2416  /// changes objective coefficient of column i to \p obj
2417  void SoPlex::changeObjRational(int i, const Rational& obj)
2418  {
2419  assert(_rationalLP != 0);
2420 
2422  return;
2423 
2424  _rationalLP->changeObj(i, obj);
2425 
2427  _realLP->changeObj(i, Real(obj));
2428 
2430  }
2431 
2432 
2433 
2434 #ifdef SOPLEX_WITH_GMP
2435  /// changes objective coefficient of column i to \p obj
2436  void SoPlex::changeObjRational(int i, const mpq_t* obj)
2437  {
2438  assert(_rationalLP != 0);
2439 
2441  return;
2442 
2443  _rationalLP->changeObj(i, obj);
2444 
2446  _realLP->changeObj(i, Real(objRational(i)));
2447 
2449  }
2450 #endif
2451 
2452 
2453 
2454  /// changes matrix entry in row \p i and column \p j to \p val
2455  void SoPlex::changeElementRational(int i, int j, const Rational& val)
2456  {
2457  assert(_rationalLP != 0);
2458 
2460  return;
2461 
2462  _rationalLP->changeElement(i, j, val);
2463 
2465  _changeElementReal(i, j, Real(val));
2466 
2468  }
2469 
2470 
2471 #ifdef SOPLEX_WITH_GMP
2472  /// changes matrix entry in row \p i and column \p j to \p val
2473  void SoPlex::changeElementRational(int i, int j, const mpq_t* val)
2474  {
2475  assert(_rationalLP != 0);
2476 
2478  return;
2479 
2480  _rationalLP->changeElement(i, j, val);
2481 
2483  _changeElementReal(i, j, mpq_get_d(*val));
2484 
2486  }
2487 #endif
2488 
2489 
2490  /// removes row \p i
2492  {
2493  assert(_rationalLP != 0);
2494 
2496  return;
2497 
2498  _rationalLP->removeRow(i);
2501  assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i)));
2502 
2504  _removeRowReal(i);
2505 
2507  }
2508 
2509 
2510 
2511  /// removes all rows with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the new
2512  /// index where row \p i has been moved to; note that \p perm must point to an array of size at least
2513  /// #numRowsRational()
2515  {
2516  assert(_rationalLP != 0);
2517 
2519  return;
2520 
2521  const int oldsize = numRowsRational();
2522  _rationalLP->removeRows(perm);
2523  for( int i = 0; i < oldsize; i++ )
2524  {
2525  if( perm[i] >= 0 )
2526  _rowTypes[perm[i]] = _rowTypes[i];
2527  }
2529  for( int i = 0; i < numRowsRational(); i++ )
2530  {
2531  assert(_rowTypes[i] == _rangeTypeRational(lhsRational(i), rhsRational(i)));
2532  }
2533 
2534 
2536  _removeRowsReal(perm);
2537 
2539  }
2540 
2541 
2542 
2543  /// remove all rows with indices in array \p idx of size \p n; an array \p perm of size #numRowsRational() may be
2544  /// passed as buffer memory
2545  void SoPlex::removeRowsRational(int idx[], int n, int perm[])
2546  {
2547  if( perm == 0 )
2548  {
2550  _idxToPerm(idx, n, p.get_ptr(), numRowsRational());
2552  }
2553  else
2554  {
2555  _idxToPerm(idx, n, perm, numRowsRational());
2557  }
2558  }
2559 
2560 
2561 
2562  /// removes rows \p start to \p end including both; an array \p perm of size #numRowsRational() may be passed as
2563  /// buffer memory
2564  void SoPlex::removeRowRangeRational(int start, int end, int perm[])
2565  {
2566  if( perm == 0 )
2567  {
2569  _rangeToPerm(start, end, p.get_ptr(), numRowsRational());
2571  }
2572  else
2573  {
2574  _rangeToPerm(start, end, perm, numRowsRational());
2576  }
2577  }
2578 
2579 
2580 
2581  /// removes column i
2583  {
2584  assert(_rationalLP != 0);
2585 
2587  return;
2588 
2589  _rationalLP->removeCol(i);
2593 
2595  _removeColReal(i);
2596 
2598  }
2599 
2600 
2601 
2602  /// removes all columns with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the
2603  /// new index where column \p i has been moved to; note that \p perm must point to an array of size at least
2604  /// #numColsRational()
2606  {
2607  assert(_rationalLP != 0);
2608 
2610  return;
2611 
2612  const int oldsize = numColsRational();
2613  _rationalLP->removeCols(perm);
2614  for( int i = 0; i < oldsize; i++ )
2615  {
2616  if( perm[i] >= 0 )
2617  _colTypes[perm[i]] = _colTypes[i];
2618  }
2620  for( int i = 0; i < numColsRational(); i++ )
2621  {
2623  }
2624 
2626  _removeColsReal(perm);
2627 
2629  }
2630 
2631 
2632 
2633  /// remove all columns with indices in array \p idx of size \p n; an array \p perm of size #numColsRational() may be
2634  /// passed as buffer memory
2635  void SoPlex::removeColsRational(int idx[], int n, int perm[])
2636  {
2637  if( perm == 0 )
2638  {
2640  _idxToPerm(idx, n, p.get_ptr(), numColsRational());
2642  }
2643  else
2644  {
2645  _idxToPerm(idx, n, perm, numColsRational());
2647  }
2648  }
2649 
2650 
2651 
2652  /// removes columns \p start to \p end including both; an array \p perm of size #numColsRational() may be passed as
2653  /// buffer memory
2654  void SoPlex::removeColRangeRational(int start, int end, int perm[])
2655  {
2656  if( perm == 0 )
2657  {
2659  _rangeToPerm(start, end, p.get_ptr(), numColsRational());
2661  }
2662  else
2663  {
2664  _rangeToPerm(start, end, perm, numColsRational());
2666  }
2667  }
2668 
2669 
2670 
2671  /// clears the LP
2673  {
2674  assert(_rationalLP != 0);
2675 
2677  return;
2678 
2679  _rationalLP->clear();
2680  _rowTypes.clear();
2681  _colTypes.clear();
2682 
2684  {
2685  _realLP->clear();
2686  _hasBasis = false;
2687  }
2688 
2690  }
2691 
2692 
2693 
2694  /// synchronizes rational LP with real LP, i.e., copies real LP to rational LP, if sync mode is manual
2696  {
2697  assert(_isConsistent());
2698 
2700  _syncLPRational();
2701  }
2702 
2703 
2704 
2705  /// solves the LP
2707  {
2708  assert(_isConsistent());
2709 
2710  // clear statistics
2712 
2713  // the solution is no longer valid
2715 
2716  // decide whether to solve the rational LP with iterative refinement or call the standard floating-point solver
2718  && GE(realParam(SoPlex::FEASTOL), 1e-9) && GE(realParam(SoPlex::OPTTOL), 1e-9)) )
2719  {
2720  // ensure that tolerances are reasonable for the floating-point solver
2722  {
2723  MSG_WARNING( spxout, spxout << "Cannot call floating-point solver with feasibility tolerance below "
2724  << _currentSettings->_realParamLower[SoPlex::FPFEASTOL] << " - relaxing tolerance\n");
2726  }
2727  else
2729 
2731  {
2732  MSG_WARNING( spxout, spxout << "Cannot call floating-point solver with optimality tolerance below "
2733  << _currentSettings->_realParamLower[SoPlex::FPOPTTOL] << " - relaxing tolerance\n");
2735  }
2736  else
2738 
2739  _solveReal();
2740  }
2742  {
2743  _syncLPRational();
2744  _solveRational();
2745  }
2747  {
2748 #ifdef ENABLE_ADDITIONAL_CHECKS
2749  assert(areLPsInSync(true, true, false));
2750 #else
2751  assert(areLPsInSync(true, false, false));
2752 #endif
2753 
2754  _solveRational();
2755 
2756 #ifdef ENABLE_ADDITIONAL_CHECKS
2757  assert(areLPsInSync(true, true, false));
2758 #else
2759  assert(areLPsInSync(true, false, false));
2760 #endif
2761  }
2762  else
2763  {
2764 #ifdef ENABLE_ADDITIONAL_CHECKS
2765  assert(areLPsInSync(true, true, false));
2766 #else
2767  assert(areLPsInSync(true, false, false));
2768 #endif
2769 
2770  _solveRational();
2771  }
2772 
2773  MSG_INFO1( spxout, spxout << "\n";
2775  spxout << "\n" );
2776 
2777  return status();
2778  }
2779 
2780 
2781 
2782  /// returns the current solver status
2784  {
2785  return _status;
2786  }
2787 
2788 
2789 
2790  /// is a primal feasible solution available?
2791  bool SoPlex::hasPrimal() const
2792  {
2794  }
2795 
2796 
2797 
2798  /// is a primal unbounded ray available?
2800  {
2802  }
2803 
2804 
2805 
2806  /// is a dual feasible solution available?
2807  bool SoPlex::hasDual() const
2808  {
2810  }
2811 
2812 
2813 
2814  /// is Farkas proof of infeasibility available?
2816  {
2818  }
2819 
2820 
2821 
2822  /// returns the objective value if a primal or dual solution is available
2824  {
2825  assert(OBJSENSE_MAXIMIZE == 1);
2826  assert(OBJSENSE_MINIMIZE == -1);
2827 
2828  if( status() == SPxSolver::UNBOUNDED )
2830  else if( status() == SPxSolver::INFEASIBLE )
2832  else if( hasPrimal() )
2833  {
2835  return _solReal._primalObjVal;
2836  }
2837  else if( hasDual() )
2838  {
2840  return _solReal._dualObjVal;
2841  }
2842  else
2843  return 0.0;
2844  }
2845 
2846 
2847 
2848  /// gets the primal solution vector if available; returns true on success
2850  {
2851  if( hasPrimal() && vector.dim() >= numColsReal() )
2852  {
2854  _solReal.getPrimal(vector);
2855  return true;
2856  }
2857  else
2858  return false;
2859  }
2860 
2861 
2862 
2863  /// gets the vector of slack values if available; returns true on success
2865  {
2866  if( hasPrimal() && vector.dim() >= numRowsReal() )
2867  {
2869  _solReal.getSlacks(vector);
2870  return true;
2871  }
2872  else
2873  return false;
2874  }
2875 
2876 
2877 
2878  /// gets the primal ray if available; returns true on success
2880  {
2881  if( hasPrimalRay() && vector.dim() >= numColsReal() )
2882  {
2884  _solReal.getPrimalRay(vector);
2885  return true;
2886  }
2887  else
2888  return false;
2889  }
2890 
2891 
2892 
2893  /// gets the dual solution vector if available; returns true on success
2895  {
2896  if( hasDual() && vector.dim() >= numRowsReal() )
2897  {
2899  _solReal.getDual(vector);
2900  return true;
2901  }
2902  else
2903  return false;
2904  }
2905 
2906 
2907 
2908  /// gets the vector of reduced cost values if available; returns true on success
2910  {
2911  if( hasDual() && vector.dim() >= numColsReal() )
2912  {
2914  _solReal.getRedCost(vector);
2915  return true;
2916  }
2917  else
2918  return false;
2919  }
2920 
2921 
2922 
2923  /// gets the Farkas proof if available; returns true on success
2925  {
2926  if( hasDualFarkas() && vector.dim() >= numRowsReal() )
2927  {
2929  _solReal.getDualFarkas(vector);
2930  return true;
2931  }
2932  else
2933  return false;
2934  }
2935 
2936 
2937 
2938  /// gets violation of bounds; returns true on success
2939  bool SoPlex::getBoundViolationReal(Real& maxviol, Real& sumviol)
2940  {
2941  if( !hasPrimal() )
2942  return false;
2943 
2945  VectorReal& primal = _solReal._primal;
2946  assert(primal.dim() == numColsReal());
2947 
2948  maxviol = 0.0;
2949  sumviol = 0.0;
2950 
2951  for( int i = numColsReal() - 1; i >= 0; i-- )
2952  {
2953  Real viol = lowerReal(i) - primal[i];
2954  if( viol > 0.0 )
2955  {
2956  sumviol += viol;
2957  if( viol > maxviol )
2958  maxviol = viol;
2959  }
2960 
2961  viol = primal[i] - upperReal(i);
2962  if( viol > 0.0 )
2963  {
2964  sumviol += viol;
2965  if( viol > maxviol )
2966  maxviol = viol;
2967  }
2968  }
2969 
2970  return true;
2971  }
2972 
2973 
2974 
2975  /// gets violation of constraints; returns true on success
2976  bool SoPlex::getRowViolationReal(Real& maxviol, Real& sumviol)
2977  {
2978  if( !hasPrimal() )
2979  return false;
2980 
2982  VectorReal& primal = _solReal._primal;
2983  assert(primal.dim() == numColsReal());
2984 
2985  DVectorReal activity(numRowsReal());
2986  _realLP->computePrimalActivity(primal, activity);
2987  maxviol = 0.0;
2988  sumviol = 0.0;
2989 
2990  for( int i = numRowsReal() - 1; i >= 0; i-- )
2991  {
2992  Real viol = lhsReal(i) - activity[i];
2993  if( viol > 0.0 )
2994  {
2995  sumviol += viol;
2996  if( viol > maxviol )
2997  maxviol = viol;
2998  }
2999 
3000  viol = activity[i] - rhsReal(i);
3001  if( viol > 0.0 )
3002  {
3003  sumviol += viol;
3004  if( viol > maxviol )
3005  maxviol = viol;
3006  }
3007  }
3008 
3009  return true;
3010  }
3011 
3012 
3013 
3014  /// gets violation of reduced costs; returns true on success
3015  bool SoPlex::getRedCostViolationReal(Real& maxviol, Real& sumviol)
3016  {
3017  if( !hasDual() || !hasBasis() )
3018  return false;
3019 
3021  VectorReal& redcost = _solReal._redCost;
3022  assert(redcost.dim() == numColsReal());
3023 
3024  maxviol = 0.0;
3025  sumviol = 0.0;
3026 
3027  for( int c = numColsReal() - 1; c >= 0; c-- )
3028  {
3029  SPxSolver::VarStatus colStatus = basisColStatus(c);
3030 
3032  {
3033  if( colStatus != SPxSolver::ON_UPPER && colStatus != SPxSolver::FIXED && redcost[c] < 0.0 )
3034  {
3035  sumviol += -redcost[c];
3036  if( redcost[c] < -maxviol )
3037  maxviol = -redcost[c];
3038  }
3039  if( colStatus != SPxSolver::ON_LOWER && colStatus != SPxSolver::FIXED && redcost[c] > 0.0 )
3040  {
3041  sumviol += redcost[c];
3042  if( redcost[c] > maxviol )
3043  maxviol = redcost[c];
3044  }
3045  }
3046  else
3047  {
3048  if( colStatus != SPxSolver::ON_UPPER && colStatus != SPxSolver::FIXED && redcost[c] > 0.0 )
3049  {
3050  sumviol += redcost[c];
3051  if( redcost[c] > maxviol )
3052  maxviol = redcost[c];
3053  }
3054  if( colStatus != SPxSolver::ON_LOWER && colStatus != SPxSolver::FIXED && redcost[c] < 0.0 )
3055  {
3056  sumviol += -redcost[c];
3057  if( redcost[c] < -maxviol )
3058  maxviol = -redcost[c];
3059  }
3060  }
3061  }
3062 
3063  return true;
3064  }
3065 
3066 
3067 
3068  /// gets violation of dual multipliers; returns true on success
3069  bool SoPlex::getDualViolationReal(Real& maxviol, Real& sumviol)
3070  {
3071  if( !hasDual() || !hasBasis() )
3072  return false;
3073 
3075  VectorReal& dual = _solReal._dual;
3076  assert(dual.dim() == numRowsReal());
3077 
3078  maxviol = 0.0;
3079  sumviol = 0.0;
3080 
3081  for( int r = numRowsReal() - 1; r >= 0; r-- )
3082  {
3083  SPxSolver::VarStatus rowStatus = basisRowStatus(r);
3084 
3086  {
3087  if( rowStatus != SPxSolver::ON_UPPER && rowStatus != SPxSolver::FIXED && dual[r] < 0.0 )
3088  {
3089  sumviol += -dual[r];
3090  if( dual[r] < -maxviol )
3091  maxviol = -dual[r];
3092  }
3093  if( rowStatus != SPxSolver::ON_LOWER && rowStatus != SPxSolver::FIXED && dual[r] > 0.0 )
3094  {
3095  sumviol += dual[r];
3096  if( dual[r] > maxviol )
3097  maxviol = dual[r];
3098  }
3099  }
3100  else
3101  {
3102  if( rowStatus != SPxSolver::ON_UPPER && rowStatus != SPxSolver::FIXED && dual[r] > 0.0 )
3103  {
3104  sumviol += dual[r];
3105  if( dual[r] > maxviol )
3106  maxviol = dual[r];
3107  }
3108  if( rowStatus != SPxSolver::ON_LOWER && rowStatus != SPxSolver::FIXED && dual[r] < 0.0 )
3109  {
3110  sumviol += -dual[r];
3111  if( dual[r] < -maxviol )
3112  maxviol = -dual[r];
3113  }
3114  }
3115  }
3116 
3117  return true;
3118  }
3119 
3120 
3121 
3122  /// returns the objective value if a primal or dual solution is available
3124  {
3125  assert(OBJSENSE_MAXIMIZE == 1);
3126  assert(OBJSENSE_MINIMIZE == -1);
3127 
3128  if( status() == SPxSolver::UNBOUNDED )
3129  {
3131  return _rationalPosInfty;
3132  else
3133  return _rationalNegInfty;
3134  }
3135  else if( status() == SPxSolver::INFEASIBLE )
3136  {
3138  return _rationalNegInfty;
3139  else
3140  return _rationalPosInfty;
3141  }
3142  else if( hasPrimal() )
3143  {
3145  return _solRational._primalObjVal;
3146  }
3147  else if( hasDual() )
3148  {
3150  return _solRational._dualObjVal;
3151  }
3152  else
3153  return Rational::ZERO;
3154  }
3155 
3156 
3157 
3158  /// gets the primal solution vector if available; returns true on success
3160  {
3161  if( hasPrimal() && vector.dim() >= numColsRational() )
3162  {
3164  _solRational.getPrimal(vector);
3165  return true;
3166  }
3167  else
3168  return false;
3169  }
3170 
3171 
3172 
3173  /// gets the vector of slack values if available; returns true on success
3175  {
3176  if( hasPrimal() && vector.dim() >= numRowsRational() )
3177  {
3179  _solRational.getSlacks(vector);
3180  return true;
3181  }
3182  else
3183  return false;
3184  }
3185 
3186 
3187 
3188  /// gets the primal ray if LP is unbounded; returns true on success
3190  {
3191  if( hasPrimalRay() && vector.dim() >= numColsRational() )
3192  {
3194  _solRational.getPrimalRay(vector);
3195  return true;
3196  }
3197  else
3198  return false;
3199  }
3200 
3201 
3202 
3203  /// gets the dual solution vector if available; returns true on success
3205  {
3206  if( hasDual() && vector.dim() >= numRowsRational() )
3207  {
3209  _solRational.getDual(vector);
3210  return true;
3211  }
3212  else
3213  return false;
3214  }
3215 
3216 
3217 
3218  /// gets the vector of reduced cost values if available; returns true on success
3220  {
3221  if( hasDual() && vector.dim() >= numColsRational() )
3222  {
3224  _solRational.getRedCost(vector);
3225  return true;
3226  }
3227  else
3228  return false;
3229  }
3230 
3231 
3232 
3233  /// gets the Farkas proof if LP is infeasible; returns true on success
3235  {
3236  if( hasDualFarkas() && vector.dim() >= numRowsRational() )
3237  {
3239  _solRational.getDualFarkas(vector);
3240  return true;
3241  }
3242  else
3243  return false;
3244  }
3245 
3246 
3247 
3248  /// gets violation of bounds; returns true on success
3250  {
3251  if( !hasPrimal() )
3252  return false;
3253 
3254  // if we have to synchronize, we do not measure time, because this would affect the solving statistics
3256  _syncLPRational(false);
3257 
3260  assert(primal.dim() == numColsRational());
3261 
3262  maxviol = 0;
3263  sumviol = 0;
3264 
3265  for( int i = numColsRational() - 1; i >= 0; i-- )
3266  {
3267  Rational viol = lowerRational(i) - primal[i];
3268  if( viol > 0 )
3269  {
3270  sumviol += viol;
3271  if( viol > maxviol )
3272  maxviol = viol;
3273  }
3274 
3275  viol = primal[i] - upperRational(i);
3276  if( viol > 0 )
3277  {
3278  sumviol += viol;
3279  if( viol > maxviol )
3280  maxviol = viol;
3281  }
3282  }
3283 
3284  return true;
3285  }
3286 
3287 
3288 
3289  /// gets violation of constraints; returns true on success
3291  {
3292  if( !hasPrimal() )
3293  return false;
3294 
3295  // if we have to synchronize, we do not measure time, because this would affect the solving statistics
3297  _syncLPRational(false);
3298 
3301  assert(primal.dim() == numColsRational());
3302 
3303  DVectorRational activity(numRowsRational());
3304  _rationalLP->computePrimalActivity(primal, activity);
3305  maxviol = 0;
3306  sumviol = 0;
3307 
3308  for( int i = numRowsRational() - 1; i >= 0; i-- )
3309  {
3310  Rational viol = lhsRational(i) - activity[i];
3311  if( viol > 0 )
3312  {
3313  sumviol += viol;
3314  if( viol > maxviol )
3315  maxviol = viol;
3316  }
3317 
3318  viol = activity[i] - rhsRational(i);
3319  if( viol > 0 )
3320  {
3321  sumviol += viol;
3322  if( viol > maxviol )
3323  maxviol = viol;
3324  }
3325  }
3326 
3327  return true;
3328  }
3329 
3330 
3331 
3332  /// gets violation of reduced costs; returns true on success
3334  {
3335  if( !hasDual() || !hasPrimal() )
3336  return false;
3337 
3338  // if we have to synchronize, we do not measure time, because this would affect the solving statistics
3340  _syncLPRational(false);
3341 
3344  assert(redcost.dim() == numColsRational());
3345 
3346  maxviol = 0;
3347  sumviol = 0;
3348 
3349  for( int c = numColsReal() - 1; c >= 0; c-- )
3350  {
3351  assert(!_hasBasis || basisColStatus(c) != SPxSolver::UNDEFINED);
3352 
3353  if( _colTypes[c] == RANGETYPE_FIXED )
3354  {
3355  assert(lowerRational(c) == upperRational(c));
3356  continue;
3357  }
3358 
3363 
3365  {
3366  if( _solRational._primal[c] != upperRational(c) && redcost[c] < 0 )
3367  {
3368  sumviol += -redcost[c];
3369  if( redcost[c] < -maxviol )
3370  {
3371  MSG_DEBUG( std::cout << "increased reduced cost violation for column " << c << " not on upper bound: " << rationalToString(-redcost[c]) << "\n" );
3372  maxviol = -redcost[c];
3373  }
3374  }
3375  if( _solRational._primal[c] != lowerRational(c) && redcost[c] > 0 )
3376  {
3377  sumviol += redcost[c];
3378  if( redcost[c] > maxviol )
3379  {
3380  MSG_DEBUG( std::cout << "increased reduced cost violation for column " << c << " not on lower bound: " << rationalToString(redcost[c]) << "\n" );
3381  maxviol = redcost[c];
3382  }
3383  }
3384  }
3385  else
3386  {
3387  if( _solRational._primal[c] != upperRational(c) && redcost[c] > 0 )
3388  {
3389  sumviol += redcost[c];
3390  if( redcost[c] > maxviol )
3391  {
3392  MSG_DEBUG( std::cout << "increased reduced cost violation for column " << c << " not on upper bound: " << rationalToString(redcost[c]) << "\n" );
3393  maxviol = redcost[c];
3394  }
3395  }
3396  if( _solRational._primal[c] != lowerRational(c) && redcost[c] < 0 )
3397  {
3398  sumviol += -redcost[c];
3399  if( redcost[c] < -maxviol )
3400  {
3401  MSG_DEBUG( std::cout << "increased reduced cost violation for column " << c << " not on lower bound: " << rationalToString(-redcost[c]) << "\n" );
3402  maxviol = -redcost[c];
3403  }
3404  }
3405  }
3406  }
3407 
3408  return true;
3409  }
3410 
3411 
3412 
3413  /// gets violation of dual multipliers; returns true on success
3415  {
3416  if( !hasDual() || !hasPrimal() )
3417  return false;
3418 
3419  // if we have to synchronize, we do not measure time, because this would affect the solving statistics
3421  _syncLPRational(false);
3422 
3425  assert(dual.dim() == numRowsRational());
3426 
3427  maxviol = 0;
3428  sumviol = 0;
3429 
3430  for( int r = numRowsReal() - 1; r >= 0; r-- )
3431  {
3432  assert(!_hasBasis || basisRowStatus(r) != SPxSolver::UNDEFINED);
3433 
3434  if( _rowTypes[r] == RANGETYPE_FIXED )
3435  {
3436  assert(lhsRational(r) == rhsRational(r));
3437  continue;
3438  }
3439 
3444 
3446  {
3447  if( _solRational._slacks[r] < rhsRational(r) - _rationalFeastol && dual[r] < 0 )
3448  {
3449  sumviol += -dual[r];
3450  if( dual[r] < -maxviol )
3451  {
3452  MSG_DEBUG( std::cout << "increased dual violation for row " << r << " not on upper bound: " << rationalToString(-dual[r])
3453  << " (slack = " << rationalToString(_solRational._slacks[r])
3454  << ", status = " << basisRowStatus(r)
3455  << ", lhs = " << rationalToString(lhsRational(r))
3456  << ", rhs = " << rationalToString(rhsRational(r)) << ")\n" );
3457  maxviol = -dual[r];
3458  }
3459  }
3460  if( _solRational._slacks[r] > lhsRational(r) + _rationalFeastol && dual[r] > 0 )
3461  {
3462  sumviol += dual[r];
3463  if( dual[r] > maxviol )
3464  {
3465  MSG_DEBUG( std::cout << "increased dual violation for row " << r << " not on lower bound: " << rationalToString(dual[r])
3466  << " (slack = " << rationalToString(_solRational._slacks[r])
3467  << ", status = " << basisRowStatus(r)
3468  << ", lhs = " << rationalToString(lhsRational(r))
3469  << ", rhs = " << rationalToString(rhsRational(r)) << ")\n" );
3470  maxviol = dual[r];
3471  }
3472  }
3473  }
3474  else
3475  {
3476  if( _solRational._slacks[r] < rhsRational(r) - _rationalFeastol && dual[r] > 0 )
3477  {
3478  sumviol += dual[r];
3479  if( dual[r] > maxviol )
3480  {
3481  MSG_DEBUG( std::cout << "increased dual violation for row " << r << " not on upper bound: " << rationalToString(dual[r])
3482  << " (slack = " << rationalToString(_solRational._slacks[r])
3483  << ", status = " << basisRowStatus(r)
3484  << ", lhs = " << rationalToString(lhsRational(r))
3485  << ", rhs = " << rationalToString(rhsRational(r)) << ")\n" );
3486  maxviol = dual[r];
3487  }
3488  }
3489  if( _solRational._slacks[r] > lhsRational(r) + _rationalFeastol && dual[r] < 0 )
3490  {
3491  sumviol += -dual[r];
3492  if( dual[r] < -maxviol )
3493  {
3494  MSG_DEBUG( std::cout << "increased dual violation for row " << r << " not on lower bound: " << rationalToString(-dual[r])
3495  << " (slack = " << rationalToString(_solRational._slacks[r])
3496  << ", status = " << basisRowStatus(r)
3497  << ", lhs = " << rationalToString(lhsRational(r))
3498  << ", rhs = " << rationalToString(rhsRational(r)) << ")\n" );
3499  maxviol = -dual[r];
3500  }
3501  }
3502  }
3503  }
3504 
3505  return true;
3506  }
3507 
3508 
3509 
3510 #ifdef SOPLEX_WITH_GMP
3511  /// gets the primal solution vector if available; returns true on success
3512  bool SoPlex::getPrimalRational(mpq_t* vector, const int size)
3513  {
3514  assert(size >= numColsRational());
3515 
3516  if( hasPrimal() )
3517  {
3519  for( int i = 0; i < numColsRational(); i++ )
3520  mpq_set(vector[i], _solRational._primal[i].getMpqRef());
3521  return true;
3522  }
3523  else
3524  return false;
3525  }
3526 
3527 
3528  /// gets the vector of slack values if available; returns true on success
3529  bool SoPlex::getSlacksRational(mpq_t* vector, const int size)
3530  {
3531  assert(size >= numRowsRational());
3532 
3533  if( hasPrimal() )
3534  {
3536  for( int i = 0; i < numRowsRational(); i++ )
3537  mpq_set(vector[i], _solRational._slacks[i].getMpqRef());
3538  return true;
3539  }
3540  else
3541  return false;
3542  }
3543 
3544 
3545 
3546  /// gets the primal ray if LP is unbounded; returns true on success
3547  bool SoPlex::getPrimalRayRational(mpq_t* vector, const int size)
3548  {
3549  assert(size >= numColsRational());
3550 
3551  if( hasPrimalRay() )
3552  {
3554  for( int i = 0; i < numColsRational(); i++ )
3555  mpq_set(vector[i], _solRational._primalRay[i].getMpqRef());
3556  return true;
3557  }
3558  else
3559  return false;
3560  }
3561 
3562 
3563 
3564  /// gets the dual solution vector if available; returns true on success
3565  bool SoPlex::getDualRational(mpq_t* vector, const int size)
3566  {
3567  assert(size >= numRowsRational());
3568 
3569  if( hasDual() )
3570  {
3572  for( int i = 0; i < numRowsRational(); i++ )
3573  mpq_set(vector[i], _solRational._dual[i].getMpqRef());
3574  return true;
3575  }
3576  else
3577  return false;
3578  }
3579 
3580 
3581 
3582  /// gets the vector of reduced cost values if available; returns true on success
3583  bool SoPlex::getRedCostRational(mpq_t* vector, const int size)
3584  {
3585  assert(size >= numColsRational());
3586 
3587  if( hasDual() )
3588  {
3590  for( int i = 0; i < numColsRational(); i++ )
3591  mpq_set(vector[i], _solRational._redCost[i].getMpqRef());
3592  return true;
3593  }
3594  else
3595  return false;
3596  }
3597 
3598 
3599 
3600  /// gets the Farkas proof if LP is infeasible; returns true on success
3601  bool SoPlex::getDualFarkasRational(mpq_t* vector, const int size)
3602  {
3603  assert(size >= numRowsRational());
3604 
3605  if( hasDualFarkas() )
3606  {
3608  for( int i = 0; i < numRowsRational(); i++ )
3609  mpq_set(vector[i], _solRational._dualFarkas[i].getMpqRef());
3610  return true;
3611  }
3612  else
3613  return false;
3614  }
3615 #endif
3616 
3617 
3618 
3619  /// get size of primal solution
3621  {
3622  if( hasPrimal() || hasPrimalRay() )
3623  {
3625  return _solRational.totalSizePrimal(base);
3626  }
3627  else
3628  return 0;
3629  }
3630 
3631 
3632 
3633  /// get size of dual solution
3634  int SoPlex::totalSizeDualRational(const int base)
3635  {
3636  if( hasDual() || hasDualFarkas() )
3637  {
3639  return _solRational.totalSizeDual(base);
3640  }
3641  else
3642  return 0;
3643  }
3644 
3645 
3646 
3647  /// get size of least common multiple of denominators in primal solution
3649  {
3650  if( hasPrimal() || hasPrimalRay() )
3651  {
3653  return _solRational.dlcmSizePrimal(base);
3654  }
3655  else
3656  return 0;
3657  }
3658 
3659 
3660 
3661  /// get size of least common multiple of denominators in dual solution
3662  int SoPlex::dlcmSizeDualRational(const int base)
3663  {
3664  if( hasDual() || hasDualFarkas() )
3665  {
3667  return _solRational.dlcmSizeDual(base);
3668  }
3669  else
3670  return 0;
3671  }
3672 
3673 
3674 
3675  /// get size of largest denominator in primal solution
3677  {
3678  if( hasPrimal() || hasPrimalRay() )
3679  {
3681  return _solRational.dmaxSizePrimal(base);
3682  }
3683  else
3684  return 0;
3685  }
3686 
3687 
3688 
3689  /// get size of largest denominator in dual solution
3690  int SoPlex::dmaxSizeDualRational(const int base)
3691  {
3692  if( hasDual() || hasDualFarkas() )
3693  {
3695  return _solRational.dmaxSizeDual(base);
3696  }
3697  else
3698  return 0;
3699  }
3700 
3701 
3702 
3703  /// is an advanced starting basis available?
3704  bool SoPlex::hasBasis() const
3705  {
3706  return _hasBasis;
3707  }
3708 
3709 
3710 
3711  /// returns the current basis status
3713  {
3714  if( !hasBasis() )
3715  return SPxBasis::NO_PROBLEM;
3716  else if( status() == SPxSolver::OPTIMAL )
3717  return SPxBasis::OPTIMAL;
3718  else if( status() == SPxSolver::UNBOUNDED )
3719  return SPxBasis::UNBOUNDED;
3720  else if( status() == SPxSolver::INFEASIBLE )
3721  return SPxBasis::INFEASIBLE;
3722  else if( hasPrimal() )
3723  return SPxBasis::PRIMAL;
3724  else if( hasDual() )
3725  return SPxBasis::DUAL;
3726  else
3727  return SPxBasis::REGULAR;
3728  }
3729 
3730 
3731 
3732  /// returns basis status for a single row
3734  {
3735  assert(row >= 0);
3736  assert(row < numRowsReal());
3737 
3738  // if no basis is available, return slack basis; if index is out of range, return basic status as for a newly
3739  // added row
3740  if( !hasBasis() || row < 0 || row >= numRowsReal() )
3741  return SPxSolver::BASIC;
3742  // if the real LP is loaded, ask solver
3743  else if( _isRealLPLoaded )
3744  {
3745  return _solver.getBasisRowStatus(row);
3746  }
3747  // if the real LP is not loaded, the basis is stored in the basis arrays of this class
3748  else
3749  {
3750  assert(row < _basisStatusRows.size());
3751  return _basisStatusRows[row];
3752  }
3753  }
3754 
3755 
3756 
3757  /// returns basis status for a single column
3759  {
3760  assert(col >= 0);
3761  assert(col < numColsReal());
3762 
3763  // if index is out of range, return nonbasic status as for a newly added unbounded column
3764  if( col < 0 || col >= numColsReal() )
3765  {
3766  return SPxSolver::ZERO;
3767  }
3768  // if no basis is available, return slack basis
3769  else if( !hasBasis() )
3770  {
3771  if( lowerReal(col) > -realParam(SoPlex::INFTY) )
3772  return SPxSolver::ON_LOWER;
3773  else if( upperReal(col) < realParam(SoPlex::INFTY) )
3774  return SPxSolver::ON_UPPER;
3775  else
3776  return SPxSolver::ZERO;
3777  }
3778  // if the real LP is loaded, ask solver
3779  else if( _isRealLPLoaded )
3780  {
3781  return _solver.getBasisColStatus(col);
3782  }
3783  // if the real LP is not loaded, the basis is stored in the basis arrays of this class
3784  else
3785  {
3786  assert(col < _basisStatusCols.size());
3787  return _basisStatusCols[col];
3788  }
3789  }
3790 
3791 
3792 
3793  /// gets current basis
3795  {
3796  // if no basis is available, return slack basis
3797  if( !hasBasis() )
3798  {
3799  for( int i = numRowsReal() - 1; i >= 0; i-- )
3800  rows[i] = SPxSolver::BASIC;
3801 
3802  for( int i = numColsReal() - 1; i >= 0; i-- )
3803  {
3804  if( lowerReal(i) > -realParam(SoPlex::INFTY) )
3805  cols[i] = SPxSolver::ON_LOWER;
3806  else if( upperReal(i) < realParam(SoPlex::INFTY) )
3807  cols[i] = SPxSolver::ON_UPPER;
3808  else
3809  cols[i] = SPxSolver::ZERO;
3810  }
3811  }
3812  // if the real LP is loaded, ask solver
3813  else if( _isRealLPLoaded )
3814  {
3815  (void)_solver.getBasis(rows, cols);
3816  }
3817  // if the real LP is not loaded, the basis is stored in the basis arrays of this class
3818  else
3819  {
3820  assert(numRowsReal() == _basisStatusRows.size());
3821  assert(numColsReal() == _basisStatusCols.size());
3822 
3823  for( int i = numRowsReal() - 1; i >= 0; i-- )
3824  rows[i] = _basisStatusRows[i];
3825 
3826  for( int i = numColsReal() - 1; i >= 0; i-- )
3827  cols[i] = _basisStatusCols[i];
3828  }
3829  }
3830 
3831 
3832 
3833  /// returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m
3834  void SoPlex::getBasisInd(int* bind) const
3835  {
3836  // if no basis is available, return slack basis
3837  if( !hasBasis() )
3838  {
3839  for( int i = 0; i < numRowsReal(); ++i )
3840  bind[i] = -1 - i;
3841  }
3842  // if the real LP is not loaded, the basis is stored in the basis arrays of this class
3843  else if( !_isRealLPLoaded )
3844  {
3845  int k = 0;
3846 
3847  assert(numRowsReal() == _basisStatusRows.size());
3848  assert(numColsReal() == _basisStatusCols.size());
3849 
3850  for( int i = 0; i < numRowsReal(); ++i )
3851  {
3853  {
3854  bind[k] = -1 - i;
3855  k++;
3856  }
3857  }
3858 
3859  for( int j = 0; j < numColsReal(); ++j )
3860  {
3862  {
3863  bind[k] = j;
3864  k++;
3865  }
3866  }
3867 
3868  assert(k == numRowsReal());
3869  }
3870  // if the real LP is loaded, the basis is stored in the solver and we need to distinguish between column and row
3871  // representation; ask the solver itself which representation it has, since the REPRESENTATION parameter of this
3872  // class might be set to automatic
3873  else if( _solver.rep() == SPxSolver::COLUMN )
3874  {
3875  for( int i = 0; i < numRowsReal(); ++i )
3876  {
3877  SPxId id = _solver.basis().baseId(i);
3878  bind[i] = (id.isSPxColId() ? _solver.number(id) : - 1 - _solver.number(id));
3879  }
3880  }
3881  // for row representation, return the complement of the basis; for this, we need to loop through all rows and columns
3882  else
3883  {
3884  assert(_solver.rep() == SPxSolver::ROW);
3885 
3886  int k = 0;
3887 
3888  for( int i = 0; i < numRowsReal(); ++i )
3889  {
3890  if( !_solver.isRowBasic(i) )
3891  {
3892  bind[k] = -1 - i;
3893  k++;
3894  }
3895  }
3896 
3897  for( int j = 0; j < numColsReal(); ++j )
3898  {
3899  if( !_solver.isColBasic(j) )
3900  {
3901  bind[k] = j;
3902  k++;
3903  }
3904  }
3905 
3906  assert(k == numRowsReal());
3907  }
3908  }
3909 
3910 
3911 
3912  /// computes an estimated condition number for the current basis matrix using the power method; returns true on success
3914  {
3916  if( !_isRealLPLoaded )
3917  return false;
3918 
3920  return false;
3921 
3922  condition = _solver.basis().getEstimatedCondition();
3923 
3924  return true;
3925  }
3926 
3927  /// computes the exact condition number for the current basis matrix using the power method; returns true on success
3929  {
3931  if( !_isRealLPLoaded )
3932  return false;
3933 
3935  return false;
3936 
3937  condition = _solver.basis().getExactCondition();
3938 
3939  return true;
3940  }
3941 
3942  /// computes row r of basis inverse; returns true on success
3943  bool SoPlex::getBasisInverseRowReal(int r, Real* coef, int* inds, int* ninds)
3944  {
3945  assert(r >= 0);
3946  assert(r < numRowsReal());
3947  assert(coef != 0);
3948 
3949  if( !hasBasis() || r < 0 || r >= numRowsReal() )
3950  return false;
3951 
3953 
3954  if( !_isRealLPLoaded )
3955  return false;
3956 
3957  // we need to distinguish between column and row representation; ask the solver itself which representation it
3958  // has, since the REPRESENTATION parameter of this class might be set to automatic
3959  if( _solver.rep() == SPxSolver::COLUMN )
3960  {
3961  int idx;
3963  try
3964  {
3966  }
3967  catch( const SPxException& E )
3968  {
3969  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while computing basis inverse row.\n" );
3970  return false;
3971  }
3972  // copy sparse data to dense result vector based on coef array
3973  if( ninds != NULL && inds != NULL )
3974  {
3975  // during solving SoPlex may have destroyed the sparsity structure so we need to restore it
3976  x.setup();
3977  *ninds = x.size();
3978  for( int i = 0; i < *ninds; ++i )
3979  {
3980  idx = x.index(i);
3981  coef[idx] = x[idx];
3982  // set sparsity pattern of coef array
3983  inds[i] = idx;
3984  }
3985  }
3986  else
3987  {
3988  VectorReal y(numRowsReal(), coef);
3989  y = x;
3990  if( ninds != NULL )
3991  *ninds = -1;
3992  }
3993  }
3994  else
3995  {
3996  assert(_solver.rep() == SPxSolver::ROW);
3997 
3998  // @todo should rhs be a reference?
3999  DSVector rhs(numColsReal());
4000  SSVector y(numColsReal());
4001  int* bind = 0;
4002  int index;
4003 
4004  // get ordering of column basis matrix
4005  spx_alloc(bind, numRowsReal());
4006  getBasisInd(bind);
4007 
4008  // get vector corresponding to requested index r
4009  index = bind[r];
4010 
4011  // r corresponds to a row vector
4012  if( index < 0 )
4013  {
4014  // transform index to actual row index
4015  index = -index - 1;
4016 
4017  // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation
4018  assert(index >= 0);
4019  assert(index < numRowsReal());
4020  assert(!_solver.isRowBasic(index));
4021 
4022  // get row vector
4023  rhs = _solver.rowVector(index);
4024  rhs *= -1.0;
4025  }
4026  // r corresponds to a column vector
4027  else
4028  {
4029  // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation
4030  assert(index < numColsReal());
4031  assert(!_solver.isColBasic(index));
4032 
4033  // get unit vector
4034  rhs = UnitVectorReal(index);
4035  }
4036 
4037  // solve system "y B = rhs", where B is the row basis matrix
4038  try
4039  {
4040  _solver.basis().solve(y, rhs);
4041  }
4042  catch( const SPxException& E )
4043  {
4044  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while computing basis inverse row.\n" );
4045  return false;
4046  }
4047 
4048  // initialize result vector x as zero
4049  memset(coef, 0, (unsigned int)numRowsReal() * sizeof(Real));
4050 
4051  // add nonzero entries
4052  for( int i = 0; i < numColsReal(); ++i )
4053  {
4054  SPxId id = _solver.basis().baseId(i);
4055 
4056  if( id.isSPxRowId() )
4057  {
4058  assert(_solver.number(id) >= 0);
4059  assert(_solver.number(id) < numRowsReal());
4060  assert(bind[r] >= 0 || _solver.number(id) != index);
4061 
4062  coef[_solver.number(id)] = y[i];
4063  }
4064  }
4065 
4066  // if r corresponds to a row vector, we have to add a 1 at position r
4067  if( bind[r] < 0 )
4068  {
4069  assert(coef[index] == 0.0);
4070  coef[index] = 1.0;
4071  }
4072 
4073  // @todo implement returning of sparsity information like in column wise case
4074  if( ninds != NULL)
4075  *ninds = -1;
4076 
4077  // free memory
4078  spx_free(bind);
4079  }
4080 
4081  return true;
4082  }
4083 
4084 
4085 
4086  /// computes column c of basis inverse; returns true on success
4087  bool SoPlex::getBasisInverseColReal(int c, Real* coef, int* inds, int* ninds)
4088  {
4089  assert(c >= 0);
4090  assert(c < numRowsReal());
4091  assert(coef != 0);
4092 
4093  if( !hasBasis() || c < 0 || c >= numRowsReal() )
4094  return false;
4095 
4097 
4098  if( !_isRealLPLoaded )
4099  return false;
4100 
4101  // we need to distinguish between column and row representation; ask the solver itself which representation it
4102  // has, since the REPRESENTATION parameter of this class might be set to automatic
4103  if( _solver.rep() == SPxSolver::COLUMN )
4104  {
4105  int idx;
4107  try
4108  {
4110  }
4111  catch( const SPxException& E )
4112  {
4113  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while computing basis inverse row.\n" );
4114  return false;
4115  }
4116  // copy sparse data to dense result vector based on coef array
4117  if( ninds != NULL && inds != NULL )
4118  {
4119  // SoPlex may have destroyed the sparsity structure so we need to restore it
4120  x.setup();
4121  *ninds = x.size();
4122  for( int i = 0; i < *ninds; ++i )
4123  {
4124  idx = x.index(i);
4125  coef[idx] = x[idx];
4126  // set sparsity pattern of coef array
4127  inds[i] = idx;
4128  }
4129  }
4130  else
4131  {
4132  VectorReal y(numColsReal(), coef);
4133  y = x;
4134  if( ninds != NULL )
4135  *ninds = -1;
4136  }
4137  }
4138  else
4139  {
4140  assert(_solver.rep() == SPxSolver::ROW);
4141 
4142  // @todo should rhs be a reference?
4143  DSVectorReal rhs(numColsReal());
4145  int* bind = 0;
4146  int index;
4147 
4148  // get ordering of column basis matrix
4149  spx_alloc(bind, numRowsReal());
4150  getBasisInd(bind);
4151 
4152  // get vector corresponding to requested index r
4153  index = bind[c];
4154 
4155  // c corresponds to a row vector
4156  if( index < 0 )
4157  {
4158  // transform index to actual row index
4159  index = -index - 1;
4160 
4161  // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation
4162  assert(index >= 0);
4163  assert(index < numRowsReal());
4164  assert(!_solver.isRowBasic(index));
4165 
4166  // get row vector
4167  rhs = _solver.rowVector(index);
4168  rhs *= -1.0;
4169  }
4170  // c corresponds to a column vector
4171  else
4172  {
4173  // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation
4174  assert(index < numColsReal());
4175  assert(!_solver.isColBasic(index));
4176 
4177  // get unit vector
4178  rhs = UnitVectorReal(index);
4179  }
4180 
4181  // solve system "y B = rhs", where B is the row basis matrix
4182  try
4183  {
4184  _solver.basis().coSolve(y, rhs);
4185  }
4186  catch( const SPxException& E )
4187  {
4188  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while computing basis inverse row.\n" );
4189  return false;
4190  }
4191 
4192  // initialize result vector x as zero
4193  memset(coef, 0, (unsigned int)numRowsReal() * sizeof(Real));
4194 
4195  // add nonzero entries
4196  for( int i = 0; i < numColsReal(); ++i )
4197  {
4198  SPxId id = _solver.basis().baseId(i);
4199 
4200  if( id.isSPxRowId() )
4201  {
4202  assert(_solver.number(id) >= 0);
4203  assert(_solver.number(id) < numRowsReal());
4204  assert(bind[c] >= 0 || _solver.number(id) != index);
4205 
4206  coef[_solver.number(id)] = y[i];
4207  }
4208  }
4209 
4210  // if r corresponds to a row vector, we have to add a 1 at position r
4211  if( bind[c] < 0 )
4212  {
4213  assert(coef[index] == 0.0);
4214  coef[index] = 1.0;
4215  }
4216 
4217  // @todo implement returning of sparsity information like in column wise case
4218  if( ninds != NULL)
4219  *ninds = -1;
4220 
4221  // free memory
4222  spx_free(bind);
4223  }
4224 
4225  return true;
4226  }
4227 
4228 
4229 
4230  /// computes dense solution of basis matrix B * sol = rhs; returns true on success
4232  {
4233  VectorReal v(numRowsReal(), rhs);
4234  VectorReal x(numRowsReal(), sol);
4235 
4236  if( !hasBasis() )
4237  return false;
4238 
4240 
4241  if( !_isRealLPLoaded )
4242  return false;
4243 
4244  // we need to distinguish between column and row representation; ask the solver itself which representation it
4245  // has, since the REPRESENTATION parameter of this class might be set to automatic; in the column case we can use
4246  // the existing factorization
4247  if( _solver.rep() == SPxSolver::COLUMN )
4248  {
4249  // solve system "x = B^-1 * A_c" to get c'th column of B^-1 * A
4250  try
4251  {
4252  _solver.basis().solve(x, v);
4253  }
4254  catch( const SPxException& E )
4255  {
4256  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while solving with basis matrix.\n" );
4257  return false;
4258  }
4259  }
4260  else
4261  {
4262  assert(_solver.rep() == SPxSolver::ROW);
4263 
4264  DSVectorReal rowrhs(numColsReal());
4266  int* bind = 0;
4267 
4268  // get ordering of column basis matrix
4269  spx_alloc(bind, numRowsReal());
4270  getBasisInd(bind);
4271 
4272  // fill right-hand side for row-based system
4273  for( int i = 0; i < numColsReal(); ++i )
4274  {
4275  SPxId id = _solver.basis().baseId(i);
4276 
4277  if( id.isSPxRowId() )
4278  {
4279  assert(_solver.number(id) >= 0);
4280  assert(_solver.number(id) < numRowsReal());
4281 
4282  rowrhs.add(i, v[_solver.number(id)]);
4283  }
4284  else
4285  {
4286  assert(rowrhs[i] == 0.0);
4287  }
4288  }
4289 
4290  // solve system "B y = rowrhs", where B is the row basis matrix
4291  try
4292  {
4293  _solver.basis().coSolve(y, rowrhs);
4294  }
4295  catch( const SPxException& E )
4296  {
4297  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while solving with basis matrix.\n" );
4298  return false;
4299  }
4300 
4301  // fill result w.r.t. order given by bind
4302  for( int i = 0; i < numRowsReal(); ++i )
4303  {
4304  int index;
4305 
4306  index = bind[i];
4307 
4308  if( index < 0 )
4309  {
4310  index = -index-1;
4311 
4312  // should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation
4313  assert(index >= 0);
4314  assert(index < numRowsReal());
4315  assert(!_solver.isRowBasic(index));
4316 
4317  x[i] = v[index] - (rowVectorReal(index) * Vector(numColsReal(), y.get_ptr()));
4318  }
4319  else
4320  {
4321  // should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation
4322  assert(index >= 0);
4323  assert(index < numColsReal());
4324  assert(!_solver.isColBasic(index));
4325 
4326  x[i] = y[index];
4327  }
4328  }
4329 
4330  // free memory
4331  spx_free(bind);
4332  }
4333  return true;
4334  }
4335 
4336 
4337 
4338  /// sets starting basis via arrays of statuses
4340  {
4341  if( _isRealLPLoaded )
4342  {
4343  assert(numRowsReal() == _solver.nRows());
4344  assert(numColsReal() == _solver.nCols());
4345 
4346  _solver.setBasis(rows, cols);
4348  }
4349  else
4350  {
4351  _basisStatusRows.reSize(numRowsReal());
4352  _basisStatusCols.reSize(numColsReal());
4353 
4354  for( int i = numRowsReal() - 1; i >= 0; i-- )
4355  _basisStatusRows[i] = rows[i];
4356 
4357  for( int j = numColsReal() - 1; j >= 0; j-- )
4358  _basisStatusCols[j] = cols[j];
4359 
4360  _hasBasis = true;
4361  }
4362  }
4363 
4364 
4365 
4366  /// clears starting basis
4368  {
4369  _solver.reLoad();
4370  _status = _solver.status();
4371  _hasBasis = false;
4372  }
4373 
4374 
4375 
4376  /// number of iterations since last call to solve
4378  {
4379  return _statistics->iterations;
4380  }
4381 
4382 
4383 
4384  /// time spent in last call to solve
4386  {
4387  return _statistics->solvingTime->time();
4388  }
4389 
4390 
4391 
4392  /// statistical information in form of a string
4393  std::string SoPlex::statisticString() const
4394  {
4395  std::stringstream s;
4396  s << "Factorizations : " << std::setw(10) << _statistics->luFactorizationsReal << std::endl
4397  << " Time spent : " << std::setw(10) << std::fixed << std::setprecision(2) << _statistics->luFactorizationTimeReal << std::endl
4398  << "Solves : " << std::setw(10) << _statistics->luSolvesReal << std::endl
4399  << " Time spent : " << std::setw(10) << _statistics->luSolveTimeReal << std::endl
4400  << "Solution time : " << std::setw(10) << std::fixed << std::setprecision(2) << solveTime() << std::endl
4401  << "Iterations : " << std::setw(10) << numIterations() << std::endl;
4402 
4403  return s.str();
4404  }
4405 
4406 
4407 
4408  /// name of starter
4410  {
4411  if( _starter )
4412  return _starter->getName();
4413  else
4414  return "none";
4415  }
4416 
4417 
4418 
4419  /// name of simplifier
4421  {
4422  if( _simplifier )
4423  return _simplifier->getName();
4424  else
4425  return "none";
4426  }
4427 
4428 
4429 
4430  /// name of scaling method after simplifier
4432  {
4433  if( _scaler )
4434  return _scaler->getName();
4435  else
4436  return "none";
4437  }
4438 
4439 
4440 
4441  /// name of currently loaded pricer
4443  {
4444  return _solver.pricer()->getName();
4445  }
4446 
4447 
4448 
4449  /// name of currently loaded ratiotester
4451  {
4452  return _solver.ratiotester()->getName();
4453  }
4454 
4455 
4456 
4457  /// reads LP file in LP or MPS format according to READMODE parameter; gets row names, column names, and
4458  /// integer variables if desired; returns true on success
4459  bool SoPlex::readFile(const char* filename, NameSet* rowNames, NameSet* colNames, DIdxSet* intVars)
4460  {
4462  return _readFileReal(filename, rowNames, colNames, intVars);
4463  else
4464  return _readFileRational(filename, rowNames, colNames, intVars);
4465  }
4466 
4467  /// writes real LP to file; LP or MPS format is chosen from the extension in \p filename; if \p rowNames and \p
4468  /// colNames are \c NULL, default names are used; if \p intVars is not \c NULL, the variables contained in it are
4469  /// marked as integer; returns true on success
4470  bool SoPlex::writeFileReal(const char* filename, const NameSet* rowNames, const NameSet* colNames, const DIdxSet* intVars) const
4471  {
4472  ///@todo implement return value
4473  _realLP->writeFile(filename, rowNames, colNames, intVars);
4474  return true;
4475  }
4476 
4477 
4478 
4479  /// writes rational LP to file; LP or MPS format is chosen from the extension in \p filename; if \p rowNames and \p
4480  /// colNames are \c NULL, default names are used; if \p intVars is not \c NULL, the variables contained in it are
4481  /// marked as integer; returns true on success
4482  bool SoPlex::writeFileRational(const char* filename, const NameSet* rowNames, const NameSet* colNames, const DIdxSet* intVars) const
4483  {
4485  return false;
4486  else
4487  {
4488  assert(_rationalLP != 0);
4489  _rationalLP->writeFile(filename, rowNames, colNames, intVars);
4490 
4491  ///@todo implement return value
4492  return true;
4493  }
4494  }
4495 
4496 
4497 
4498  /// reads basis information from \p filename and returns true on success; if \p rowNames and \p colNames are \c NULL,
4499  /// default names are assumed; returns true on success
4500  bool SoPlex::readBasisFile(const char* filename, const NameSet* rowNames, const NameSet* colNames)
4501  {
4502 #if 1
4503  assert(filename != 0);
4504  assert(_realLP != 0);
4505 
4506  // start timing
4508 
4509  // read
4510  if( !_isRealLPLoaded )
4511  {
4512  assert(_realLP != &_solver);
4513 
4515  _realLP->~SPxLPReal();
4516  spx_free(_realLP);
4517  _realLP = &_solver;
4518  _isRealLPLoaded = true;
4519  }
4520  _hasBasis = _solver.readBasisFile(filename, rowNames, colNames);
4521  assert(_hasBasis == (_solver.basis().status() > SPxBasis::NO_PROBLEM));
4522 
4523  // stop timing
4525 
4526  return _hasBasis;
4527 #else
4528  // this is alternative code for reading bases without the SPxSolver class
4529  assert(filename != 0);
4530 
4531  // start timing
4533 
4534  // read
4535  spxifstream file(filename);
4536 
4537  if( !file )
4538  return false;
4539 
4540  // get problem size
4541  int numRows = numRowsReal();
4542  int numCols = numColsReal();
4543 
4544  // prepare column names
4545  const NameSet* colNamesPtr = colNames;
4546  NameSet* tmpColNames = 0;
4547  if( colNames == 0 )
4548  {
4549  std::stringstream name;
4550 
4551  spx_alloc(tmpColNames);
4552  tmpColNames = new (tmpColNames) NameSet();
4553  tmpColNames->reMax(numCols);
4554 
4555  for( int j = 0; j < numCols; ++j )
4556  {
4557  name << "x" << j;
4558  tmpColNames->add(name.str().c_str());
4559  }
4560 
4561  colNamesPtr = tmpColNames;
4562  }
4563 
4564  // prepare row names
4565  const NameSet* rowNamesPtr = rowNames;
4566  NameSet* tmpRowNames = 0;
4567  if( rowNamesPtr == 0 )
4568  {
4569  std::stringstream name;
4570 
4571  spx_alloc(tmpRowNames);
4572  tmpRowNames = new (tmpRowNames) NameSet();
4573  tmpRowNames->reMax(numRows);
4574 
4575  for( int i = 0; i < numRows; ++i )
4576  {
4577  name << "C" << i;
4578  tmpRowNames->add(name.str().c_str());
4579  }
4580 
4581  rowNamesPtr = tmpRowNames;
4582  }
4583 
4584  // initialize with default slack basis
4585  _basisStatusRows.reSize(numRows);
4586  _basisStatusCols.reSize(numCols);
4587 
4588  for( int i = 0; i < numRows; i++ )
4590 
4591  for( int i = 0; i < numCols; i++ )
4592  {
4593  if( lowerReal(i) == upperReal(i) )
4595  else if( lowerReal(i) <= double(-realParam(SoPlex::INFTY)) && upperReal(i) >= double(realParam(SoPlex::INFTY)) )
4597  else if( lowerReal(i) <= double(-realParam(SoPlex::INFTY)) )
4599  else
4601  }
4602 
4603  // read basis
4604  MPSInput mps(file);
4605  if( mps.readLine() && (mps.field0() != 0) && !strcmp(mps.field0(), "NAME") )
4606  {
4607  while( mps.readLine() )
4608  {
4609  int c = -1;
4610  int r = -1;
4611 
4612  if( mps.field0() != 0 && !strcmp(mps.field0(), "ENDATA") )
4613  {
4615  break;
4616  }
4617 
4618  if( mps.field1() == 0 || mps.field2() == 0 )
4619  break;
4620 
4621  if( (c = colNamesPtr->number(mps.field2())) < 0 )
4622  break;
4623 
4624  if( *mps.field1() == 'X' )
4625  {
4626  if( mps.field3() == 0 || (r = rowNamesPtr->number(mps.field3())) < 0 )
4627  break;
4628  }
4629 
4630  if( !strcmp(mps.field1(), "XU") )
4631  {
4635  else if( _rowTypes[r] == SoPlex::RANGETYPE_FIXED )
4637  else
4639  }
4640  else if( !strcmp(mps.field1(), "XL") )
4641  {
4645  else if( _rowTypes[r] == SoPlex::RANGETYPE_FIXED )
4647  else
4649  }
4650  else if( !strcmp(mps.field1(), "UL") )
4651  {
4653  }
4654  else if( !strcmp(mps.field1(), "LL") )
4655  {
4657  }
4658  else
4659  {
4660  mps.syntaxError();
4661  break;
4662  }
4663  }
4664  }
4665 
4666  if( rowNames == 0 )
4667  {
4668  tmpRowNames->~NameSet();
4669  spx_free(tmpRowNames);
4670  }
4671 
4672  if( colNames == 0 )
4673  {
4674  tmpColNames->~NameSet();
4675  spx_free(tmpColNames);
4676  }
4677 
4678  _hasBasis = !mps.hasError();
4679 
4680  // stop timing
4682 
4683  return _hasBasis;
4684 #endif
4685  }
4686 
4687 
4688 
4689  /// writes basis information to \p filename; if \p rowNames and \p colNames are \c NULL, default names are used;
4690  /// returns true on success
4691  bool SoPlex::writeBasisFile(const char* filename, const NameSet* rowNames, const NameSet* colNames, const bool cpxFormat) const
4692  {
4693  assert(filename != 0);
4694 
4695  if( _isRealLPLoaded )
4696  return _solver.writeBasisFile(filename, rowNames, colNames, cpxFormat);
4697  else
4698  {
4699  std::ofstream file(filename);
4700  if( !file.good() )
4701  return false;
4702 
4703  file.setf(std::ios::left);
4704  file << "NAME " << filename << "\n";
4705 
4706  // do not write basis if there is none
4707  if( !_hasBasis )
4708  {
4709  file << "ENDATA\n";
4710  return true;
4711  }
4712 
4713  // start writing
4714  int numRows = _basisStatusRows.size();
4715  int numCols = _basisStatusCols.size();
4716  int row = 0;
4717 
4718  for( int col = 0; col < numCols; col++ )
4719  {
4720  assert(_basisStatusCols[col] != SPxSolver::UNDEFINED);
4721 
4722  if( _basisStatusCols[col] == SPxSolver::BASIC )
4723  {
4724  // find nonbasic row
4725  for( ; row < numRows; row++ )
4726  {
4727  assert(_basisStatusRows[row] != SPxSolver::UNDEFINED);
4728  if( _basisStatusRows[row] != SPxSolver::BASIC )
4729  break;
4730  }
4731 
4732  assert(row != numRows);
4733 
4734  if( _basisStatusRows[row] == SPxSolver::ON_UPPER && (!cpxFormat || _rowTypes[row] == SoPlex::RANGETYPE_BOXED) )
4735  file << " XU ";
4736  else
4737  file << " XL ";
4738 
4739  file << std::setw(8);
4740  if( colNames != 0 && colNames->has(col) )
4741  file << (*colNames)[col];
4742  else
4743  file << "x" << col;
4744 
4745  file << " ";
4746  if( rowNames != 0 && rowNames->has(row) )
4747  file << (*rowNames)[row];
4748  else
4749  file << "C" << row;
4750 
4751  file << "\n";
4752  row++;
4753  }
4754  else
4755  {
4757  {
4758  file << " UL ";
4759 
4760  file << std::setw(8);
4761  if( colNames != 0 && colNames->has(col) )
4762  file << (*colNames)[col];
4763  else
4764  file << "x" << col;
4765 
4766  file << "\n";
4767  }
4768  }
4769  }
4770 
4771  file << "ENDATA\n";
4772 
4773 #ifndef NDEBUG
4774  // check that the remaining rows are basic
4775  for( ; row < numRows; row++ )
4776  {
4777  assert(_basisStatusRows[row] == SPxSolver::BASIC);
4778  }
4779 #endif
4780 
4781  return true;
4782  }
4783  }
4784 
4785 
4786 
4787  /// writes internal LP, basis information, and parameter settings; if \p rowNames and \p colNames are \c NULL,
4788  /// default names are used
4789  void SoPlex::writeStateReal(const char* filename, const NameSet* rowNames, const NameSet* colNames, const bool cpxFormat) const
4790  {
4791  std::string ofname;
4792 
4793  // write parameter settings
4794  ofname = std::string(filename) + ".set";
4795  saveSettingsFile(ofname.c_str());
4796 
4797  // write problem in MPS format
4798  ofname = std::string(filename) + ".mps";
4799  writeFileReal(ofname.c_str(), rowNames, colNames, 0);
4800 
4801  // write basis
4802  ofname = std::string(filename) + ".bas";
4803  writeBasisFile(ofname.c_str(), rowNames, colNames, cpxFormat);
4804  }
4805 
4806 
4807 
4808  /// writes internal LP, basis information, and parameter settings; if \p rowNames and \p colNames are \c NULL,
4809  /// default names are used
4810  void SoPlex::writeStateRational(const char* filename, const NameSet* rowNames, const NameSet* colNames, const bool cpxFormat) const
4811  {
4812  std::string ofname;
4813 
4814  // write parameter settings
4815  ofname = std::string(filename) + ".set";
4816  saveSettingsFile(ofname.c_str());
4817 
4818  // write problem in MPS format
4819  ofname = std::string(filename) + ".mps";
4820  writeFileRational(ofname.c_str(), rowNames, colNames, 0);
4821 
4822  // write basis
4823  ofname = std::string(filename) + ".bas";
4824  writeBasisFile(ofname.c_str(), rowNames, colNames, cpxFormat);
4825  }
4826 
4827 
4828 
4829  /// returns boolean parameter value
4830  bool SoPlex::boolParam(const BoolParam param) const
4831  {
4832  assert(param >= 0);
4833  assert(param < SoPlex::BOOLPARAM_COUNT);
4834  return _currentSettings->_boolParamValues[param];
4835  }
4836 
4837 
4838 
4839  /// returns integer parameter value
4840  int SoPlex::intParam(const IntParam param) const
4841  {
4842  assert(param >= 0);
4843  assert(param < INTPARAM_COUNT);
4844  return _currentSettings->_intParamValues[param];
4845  }
4846 
4847 
4848 
4849  /// returns real parameter value
4850  Real SoPlex::realParam(const RealParam param) const
4851  {
4852  assert(param >= 0);
4853  assert(param < REALPARAM_COUNT);
4854  return _currentSettings->_realParamValues[param];
4855  }
4856 
4857 
4858 
4859 #ifdef SOPLEX_WITH_RATIONALPARAM
4860  /// returns rational parameter value
4861  Rational SoPlex::rationalParam(const RationalParam param) const
4862  {
4863  assert(param >= 0);
4864  assert(param < RATIONALPARAM_COUNT);
4865  return _currentSettings->_rationalParamValues[param];
4866  }
4867 #endif
4868 
4869 
4870 
4871  /// returns current parameter settings
4873  {
4874  return *_currentSettings;
4875  }
4876 
4877 
4878 
4879  /// sets boolean parameter value; returns true on success
4880  bool SoPlex::setBoolParam(const BoolParam param, const bool value, const bool quiet, const bool init)
4881  {
4882  assert(param >= 0);
4883  assert(param < SoPlex::BOOLPARAM_COUNT);
4884  assert(init || _isConsistent());
4885 
4886  if( !init && value == boolParam(param) )
4887  return true;
4888 
4889  switch( param )
4890  {
4891  case LIFTING:
4892  break;
4893  case EQTRANS:
4894  break;
4895  case TESTDUALINF:
4896  break;
4897  case RATFAC:
4898  break;
4899  case ACCEPTCYCLING:
4900  break;
4901  case RATREC:
4902  break;
4903  case POWERSCALING:
4904  break;
4905  case RATFACJUMP:
4906  break;
4907  case FEASRELAX:
4908  break;
4909  case ROWBOUNDFLIPS:
4911  break;
4912  default:
4913  return false;
4914  }
4915 
4916  _currentSettings->_boolParamValues[param] = value;
4917  return true;
4918  }
4919 
4920 
4921 
4922  /// sets integer parameter value; returns true on success
4923  bool SoPlex::setIntParam(const IntParam param, const int value, const bool quiet, const bool init)
4924  {
4925  assert(param >= 0);
4926  assert(param < INTPARAM_COUNT);
4927  assert(init || _isConsistent());
4928 
4929  if( !init && value == intParam(param) )
4930  return true;
4931 
4932  // check for a valid parameter value wrt bounds
4933  if( value < _currentSettings->_intParamLower[param] || value > _currentSettings->_intParamUpper[param] )
4934  return false;
4935 
4936  switch( param )
4937  {
4938  // objective sense
4939  case SoPlex::OBJSENSE:
4940  if( value != SoPlex::OBJSENSE_MAXIMIZE && value != SoPlex::OBJSENSE_MINIMIZE )
4941  return false;
4943  if( _rationalLP != 0 )
4946  break;
4947 
4948  // type of computational form, i.e., column or row representation
4951  return false;
4952  break;
4953 
4954  // type of algorithm, i.e., primal or dual
4955  case SoPlex::ALGORITHM:
4956  // decide upon entering/leaving at solve time depending on representation
4957  break;
4958 
4959  // type of LU update
4962  return false;
4964  break;
4965 
4966  // maximum number of updates before fresh factorization
4968  _solver.basis().setMaxUpdates(value);
4969  break;
4970 
4971  // iteration limit (-1 if unlimited)
4972  case SoPlex::ITERLIMIT:
4973  break;
4974 
4975  // refinement limit (-1 if unlimited)
4976  case SoPlex::REFLIMIT:
4977  break;
4978 
4979  // stalling refinement limit (-1 if unlimited)
4980  case SoPlex::STALLREFLIMIT:
4981  break;
4982 
4983  // display frequency
4984  case SoPlex::DISPLAYFREQ:
4985  _solver.setDisplayFreq(value);
4986  break;
4987 
4988  // verbosity level
4989  case SoPlex::VERBOSITY:
4990  switch(value)
4991  {
4992  case 0:
4994  break;
4995  case 1:
4997  break;
4998  case 2:
5000  break;
5001  case 3:
5003  break;
5004  case 4:
5006  break;
5007  case 5:
5009  break;
5010  }
5011  break;
5012 
5013  // type of simplifier
5014  case SoPlex::SIMPLIFIER:
5015  switch( value )
5016  {
5017  case SIMPLIFIER_OFF:
5018  _simplifier = 0;
5019  break;
5020  case SIMPLIFIER_AUTO:
5022  assert(_simplifier != 0);
5023  break;
5024  default:
5025  return false;
5026  }
5027  break;
5028 
5029  // type of scaler
5030  case SoPlex::SCALER:
5031  switch( value )
5032  {
5033  case SCALER_OFF:
5034  _scaler = 0;
5035  break;
5036  case SCALER_UNIEQUI:
5038  break;
5039  case SCALER_BIEQUI:
5041  break;
5042  case SCALER_GEO1:
5043  _scaler = &_scalerGeo1;
5044  break;
5045  case SCALER_GEO8:
5046  _scaler = &_scalerGeo8;
5047  break;
5048  default:
5049  return false;
5050  }
5051  break;
5052 
5053  // type of starter used to create crash basis
5054  case SoPlex::STARTER:
5055  switch( value )
5056  {
5057  case STARTER_OFF:
5058  _starter = 0;
5059  break;
5060  case STARTER_WEIGHT:
5062  break;
5063  case STARTER_SUM:
5064  _starter = &_starterSum;
5065  break;
5066  case STARTER_VECTOR:
5068  break;
5069  default:
5070  return false;
5071  }
5072  break;
5073 
5074  // type of pricer
5075  case SoPlex::PRICER:
5076  switch( value )
5077  {
5078  case PRICER_AUTO:
5080  break;
5081  case PRICER_DANTZIG:
5083  break;
5084  case PRICER_PARMULT:
5086  break;
5087  case PRICER_DEVEX:
5089  break;
5090  case PRICER_QUICKSTEEP:
5092  break;
5093  case PRICER_STEEP:
5095  break;
5096  default:
5097  return false;
5098  }
5099  break;
5100 
5101  // mode for synchronizing real and rational LP
5102  case SoPlex::SYNCMODE:
5103  switch( value )
5104  {
5105  case SYNCMODE_ONLYREAL:
5106  if( _rationalLP != 0 )
5107  {
5108  _rationalLP->~SPxLPRational();
5110  }
5111  break;
5112  case SYNCMODE_AUTO:
5113  if( intParam(param) == SYNCMODE_ONLYREAL )
5114  _syncLPRational();
5115  break;
5116  case SYNCMODE_MANUAL:
5118  break;
5119  default:
5120  return false;
5121  }
5122  break;
5123 
5124  // mode for reading LP files; nothing to do but change the value if valid
5125  case SoPlex::READMODE:
5126  switch( value )
5127  {
5128  case READMODE_REAL:
5129  case READMODE_RATIONAL:
5130  break;
5131  default:
5132  return false;
5133  }
5134  break;
5135 
5136  // mode for iterative refinement strategy; nothing to do but change the value if valid
5137  case SoPlex::SOLVEMODE:
5138  switch( value )
5139  {
5140  case SOLVEMODE_REAL:
5141  case SOLVEMODE_AUTO:
5142  case SOLVEMODE_RATIONAL:
5143  break;
5144  default:
5145  return false;
5146  }
5147  break;
5148 
5149  // mode for a posteriori feasibility checks; nothing to do but change the value if valid
5150  case SoPlex::CHECKMODE:
5151  switch( value )
5152  {
5153  case CHECKMODE_REAL:
5154  case CHECKMODE_AUTO:
5155  case CHECKMODE_RATIONAL:
5156  break;
5157  default:
5158  return false;
5159  }
5160  break;
5161 
5162  // type of ratio test
5163  case SoPlex::RATIOTESTER:
5164  switch( value )
5165  {
5166  case RATIOTESTER_TEXTBOOK:
5168  break;
5169  case RATIOTESTER_HARRIS:
5171  break;
5172  case RATIOTESTER_FAST:
5174  break;
5177  break;
5178  default:
5179  return false;
5180  }
5181  break;
5182 
5183  // type of timer
5184  case SoPlex::TIMER:
5185  switch( value )
5186  {
5187  case TIMER_OFF:
5189  break;
5190  case TIMER_CPU:
5192  break;
5193  case TIMER_WALLCLOCK:
5195  break;
5196  default:
5197  return false;
5198  }
5199  break;
5200 
5201  // mode of hyper pricing
5202  case SoPlex::HYPER_PRICING:
5203  switch( value )
5204  {
5205  case HYPER_PRICING_OFF:
5206  case HYPER_PRICING_AUTO:
5207  case HYPER_PRICING_ON:
5208  break;
5209  default:
5210  return false;
5211  }
5212  break;
5213 
5214  // minimum number of stalling refinements since last pivot to trigger rational factorization
5216  break;
5217 
5218  default:
5219  return false;
5220  }
5221 
5222  _currentSettings->_intParamValues[param] = value;
5223  return true;
5224  }
5225 
5226 
5227 
5228  /// sets real parameter value; returns true on success
5229  bool SoPlex::setRealParam(const RealParam param, const Real value, const bool quiet, const bool init)
5230  {
5231  assert(param >= 0);
5232  assert(param < REALPARAM_COUNT);
5233  assert(init || _isConsistent());
5234 
5235  if( !init && value == realParam(param) )
5236  return true;
5237 
5238  if( value < _currentSettings->_realParamLower[param] || value > _currentSettings->_realParamUpper[param] )
5239  return false;
5240 
5241  switch( param )
5242  {
5243  // primal feasibility tolerance; passed to the floating point solver only when calling solve()
5244  case SoPlex::FEASTOL:
5245  _rationalFeastol = value;
5246  break;
5247 
5248  // dual feasibility tolerance; passed to the floating point solver only when calling solve()
5249  case SoPlex::OPTTOL:
5250  _rationalOpttol = value;
5251  break;
5252 
5253  // general zero tolerance
5254  case SoPlex::EPSILON_ZERO:
5255  Param::setEpsilon(value);
5256  break;
5257 
5258  // zero tolerance used in factorization
5261  break;
5262 
5263  // zero tolerance used in update of the factorization
5265  Param::setEpsilonUpdate(value);
5266  break;
5267 
5268  // pivot zero tolerance used in factorization (declare numerical singularity for small LU pivots)
5269  case SoPlex::EPSILON_PIVOT:
5270  Param::setEpsilonPivot(value);
5271  break;
5272 
5273  // infinity threshold
5274  case SoPlex::INFTY:
5275  _rationalPosInfty = value;
5276  _rationalNegInfty = -value;
5279  break;
5280 
5281  // time limit in seconds (INFTY if unlimited)
5282  case SoPlex::TIMELIMIT:
5283  break;
5284 
5285  // lower limit on objective value is set in solveReal()
5287  break;
5288 
5289  // upper limit on objective value is set in solveReal()
5291  break;
5292 
5293  // working tolerance for feasibility in floating-point solver
5294  case SoPlex::FPFEASTOL:
5295  break;
5296 
5297  // working tolerance for optimality in floating-point solver
5298  case SoPlex::FPOPTTOL:
5299  break;
5300 
5301  // maximum increase of scaling factors between refinements
5302  case SoPlex::MAXSCALEINCR:
5303  _rationalMaxscaleincr = value;
5304  break;
5305 
5306  // lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformulated)
5307  case SoPlex::LIFTMINVAL:
5308  break;
5309 
5310  // upper threshold in lifting (nonzero matrix coefficients with larger absolute value will be reformulated)
5311  case SoPlex::LIFTMAXVAL:
5312  break;
5313 
5314  // threshold for sparse pricing
5316  break;
5317 
5318  // threshold on number of rows vs. number of columns for switching from column to row representations in auto mode
5320  break;
5321 
5322  // geometric frequency at which to apply rational reconstruction
5323  case SoPlex::RATREC_FREQ:
5324  break;
5325 
5326  // minimal reduction (sum of removed rows/cols) to continue simplification
5327  case SoPlex::MINRED:
5328  break;
5329 
5330  default:
5331  return false;
5332  }
5333 
5334  _currentSettings->_realParamValues[param] = value;
5335  return true;
5336  }
5337 
5338 
5339 
5340 #ifdef SOPLEX_WITH_RATIONALPARAM
5341  /// sets rational parameter value; returns true on success
5342  bool SoPlex::setRationalParam(const RationalParam param, const Rational value, const bool quiet, const bool init)
5343  {
5344  assert(param >= 0);
5345  assert(param < RATIONALPARAM_COUNT);
5346  assert(init || _isConsistent());
5347 
5348  if( !init && value == rationalParam(param) )
5349  return true;
5350 
5351  if( value < _currentSettings->_rationalParamLower[param] || value > _currentSettings->_rationalParamUpper[param] )
5352  return false;
5353 
5354  switch( param )
5355  {
5356  default:
5357  // currently, there are no rational-valued parameters
5358  return false;
5359  }
5360 
5361  _currentSettings->_rationalParamValues[param] = value;
5362  return true;
5363  }
5364 #endif
5365 
5366 
5367 
5368  /// sets parameter settings; returns true on success
5369  bool SoPlex::setSettings(const Settings& newSettings, const bool quiet, const bool init)
5370  {
5371  assert(init || _isConsistent());
5372 
5373  bool success = true;
5374 
5375  *_currentSettings = newSettings;
5376 
5377  for( int i = 0; i < SoPlex::BOOLPARAM_COUNT; i++ )
5378  success &= setBoolParam((BoolParam)i, _currentSettings->_boolParamValues[i], quiet, init);
5379 
5380  for( int i = 0; i < SoPlex::INTPARAM_COUNT; i++ )
5381  success &= setIntParam((IntParam)i, _currentSettings->_intParamValues[i], quiet, init);
5382 
5383  for( int i = 0; i < SoPlex::REALPARAM_COUNT; i++ )
5384  success &= setRealParam((RealParam)i, _currentSettings->_realParamValues[i], quiet, init);
5385 
5386 #ifdef SOPLEX_WITH_RATIONALPARAM
5387  for( int i = 0; i < SoPlex::RATIONALPARAM_COUNT; i++ )
5388  success &= setRationalParam((RationalParam)i, _currentSettings->_rationalParamValues[i], quiet, init);
5389 #endif
5390 
5391  assert(_isConsistent());
5392 
5393  return success;
5394  }
5395 
5396 
5397 
5398  /// print non-default parameter values
5400  {
5401  bool printedValue = false;
5402 
5403  for( int i = 0; i < SoPlex::BOOLPARAM_COUNT; i++ )
5404  {
5406  continue;
5407 
5408  spxout << "bool:" << _currentSettings->_boolParamName[i] << " = " << (_currentSettings->_boolParamValues[i] ? "true\n" : "false\n");
5409  printedValue = true;
5410  }
5411 
5412  for( int i = 0; i < SoPlex::INTPARAM_COUNT; i++ )
5413  {
5415  continue;
5416 
5417  spxout << "int:" << _currentSettings->_intParamName[i] << " = " << _currentSettings->_intParamValues[i] << "\n";
5418  printedValue = true;
5419  }
5420 
5421  for( int i = 0; i < SoPlex::REALPARAM_COUNT; i++ )
5422  {
5424  continue;
5425 
5426  spxout << "real:" << _currentSettings->_realParamName[i] << " = " << _currentSettings->_realParamValues[i] << "\n";
5427  printedValue = true;
5428  }
5429 
5430 #ifdef SOPLEX_WITH_RATIONALPARAM
5431  for( int i = 0; i < SoPlex::RATIONALPARAM_COUNT; i++ )
5432  {
5433  if( _currentSettings->_rationalParamValues[i] == _currentSettings->_rationalParamDefault[i] )
5434  continue;
5435 
5436  spxout << "rational:" << _currentSettings->_rationalParamName[i] << " = " << _currentSettings->_rationalParamValues[i] << "\n";
5437  printedValue = true;
5438  }
5439 #endif
5440  if( printedValue )
5441  spxout << std::endl;
5442  }
5443 
5444 
5445 
5446  /// writes settings file; returns true on success
5447  bool SoPlex::saveSettingsFile(const char* filename, const bool onlyChanged) const
5448  {
5449  assert(filename != 0);
5450 
5451  std::ofstream file(filename);
5452  if( !file.good() )
5453  return false;
5454 
5455  file.setf(std::ios::left);
5456  file << "# SoPlex version " << SOPLEX_VERSION / 100 << "." << (SOPLEX_VERSION / 10) % 10 << "." << SOPLEX_VERSION % 10 << "." << SOPLEX_SUBVERSION << "\n";
5457 
5458  for( int i = 0; i < SoPlex::BOOLPARAM_COUNT; i++ )
5459  {
5461  continue;
5462 
5463  file << "\n";
5464  file << "# " << _currentSettings->_boolParamDescription[i] << "\n";
5465  file << "# range {true, false}, default " << (_currentSettings->_boolParamDefault[i] ? "true\n" : "false\n");
5466  file << "bool:" << _currentSettings->_boolParamName[i] << " = " << (_currentSettings->_boolParamValues[i] ? "true\n" : "false\n");
5467  }
5468 
5469  for( int i = 0; i < SoPlex::INTPARAM_COUNT; i++ )
5470  {
5471  if( onlyChanged && _currentSettings->_intParamValues[i] == _currentSettings->_intParamDefault[i] )
5472  continue;
5473 
5474  file << "\n";
5475  file << "# " << _currentSettings->_intParamDescription[i] << "\n";
5476  file << "# range [-2147483648,2147483647], default " << _currentSettings->_intParamDefault[i] << "\n";
5477  file << "int:" << _currentSettings->_intParamName[i] << " = " << _currentSettings->_intParamValues[i] << "\n";
5478  }
5479 
5480  for( int i = 0; i < SoPlex::REALPARAM_COUNT; i++ )
5481  {
5483  continue;
5484 
5485  file << "\n";
5486  file << "# " << _currentSettings->_realParamDescription[i] << "\n";
5487  file << "# range [" << _currentSettings->_realParamLower[i] << "," << _currentSettings->_realParamUpper[i]
5488  << "], default " << _currentSettings->_realParamDefault[i] << "\n";
5489  file << "real:" << _currentSettings->_realParamName[i] << " = " << _currentSettings->_realParamValues[i] << "\n";
5490  }
5491 
5492 #ifdef SOPLEX_WITH_RATIONALPARAM
5493  for( int i = 0; i < SoPlex::RATIONALPARAM_COUNT; i++ )
5494  {
5495  if( onlyChanged && _currentSettings->_rationalParamValues[i] == _currentSettings->_rationalParamDefault[i] )
5496  continue;
5497 
5498  file << "\n";
5499  file << "# " << _currentSettings->_rationalParamDescription[i] << "\n";
5500  file << "# range [" << _currentSettings->_rationalParamLower[i] << "," << _currentSettings->_rationalParamUpper[i]
5501  << "], default " << _currentSettings->_rationalParamDefault[i] << "\n";
5502  file << "rational:" << _currentSettings->_rationalParamName[i] << " = " << _currentSettings->_rationalParamValues[i] << "\n";
5503  }
5504 #endif
5505 
5506  return true;
5507  }
5508 
5509 
5510 
5511  /// reads settings file; returns true on success
5512  bool SoPlex::loadSettingsFile(const char* filename)
5513  {
5514  assert(filename != 0);
5515 
5516  // start timing
5518 
5519  MSG_INFO1( spxout, spxout << "Loading settings file <" << filename << "> . . .\n" );
5520 
5521  // open file
5522  spxifstream file(filename);
5523 
5524  if( !file )
5525  {
5526  MSG_ERROR( std::cerr << "Error opening settings file.\n" );
5527  return false;
5528  }
5529 
5530  // read file
5531  char line[SET_MAX_LINE_LEN];
5532  int lineNumber = 0;
5533  bool readError = false;
5534  bool parseError = false;
5535 
5536  while( !readError && !parseError)
5537  {
5538  lineNumber++;
5539  readError = !file.getline(line, sizeof(line));
5540  if( !readError )
5541  parseError = !_parseSettingsLine(line, lineNumber);
5542  }
5543  readError = readError && !file.eof();
5544 
5545  if( readError && strlen(line) == SET_MAX_LINE_LEN - 1 )
5546  {
5547  MSG_ERROR( std::cerr << "Error reading settings file: line " << lineNumber << " in settings file exceeds " << SET_MAX_LINE_LEN - 2 << " characters.\n" );
5548  }
5549  else if( readError )
5550  {
5551  MSG_ERROR( std::cerr << "Error reading settings file: line " << lineNumber << ".\n" );
5552  }
5553 
5554  // stop timing
5556 
5557  return !readError && !parseError;
5558  }
5559 
5560  /// parses one setting string and returns true on success
5561  bool SoPlex::parseSettingsString(char* string)
5562  {
5563  assert(string != 0);
5564  if( string == 0 )
5565  return false;
5566 
5567  char parseString[SET_MAX_LINE_LEN];
5568  strncpy(parseString, string, SET_MAX_LINE_LEN-1);
5569  parseString[SET_MAX_LINE_LEN-1] = '\0';
5570 
5571  char* line = parseString;
5572 
5573  // find the start of the parameter type
5574  while( *line == ' ' || *line == '\t' || *line == '\r' )
5575  line++;
5576  if( *line == '\0' || *line == '\n' || *line == '#' )
5577  return true;
5578  char* paramTypeString = line;
5579 
5580  // find the end of the parameter type
5581  while( *line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' && *line != '\0' && *line != ':' )
5582  line++;
5583  if( *line == ':' )
5584  {
5585  *line = '\0';
5586  line++;
5587  }
5588  else
5589  {
5590  *line = '\0';
5591  line++;
5592 
5593  // search for the ':' char in the line
5594  while( *line == ' ' || *line == '\t' || *line == '\r' )
5595  line++;
5596  if( *line != ':' )
5597  {
5598  MSG_ERROR( std::cerr << "Error parsing setting string: no ':' separating parameter type and name.\n" );
5599  return false;
5600  }
5601  line++;
5602  }
5603 
5604  // find the start of the parameter name
5605  while( *line == ' ' || *line == '\t' || *line == '\r' )
5606  line++;
5607  if( *line == '\0' || *line == '\n' || *line == '#' )
5608  {
5609  MSG_ERROR( std::cerr << "Error parsing setting string: no parameter name.\n");
5610  return false;
5611  }
5612  char* paramName = line;
5613 
5614  // find the end of the parameter name
5615  while( *line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' && *line != '\0' && *line != '=' )
5616  line++;
5617  if( *line == '=' )
5618  {
5619  *line = '\0';
5620  line++;
5621  }
5622  else
5623  {
5624  *line = '\0';
5625  line++;
5626 
5627  // search for the '=' char in the line
5628  while( *line == ' ' || *line == '\t' || *line == '\r' )
5629  line++;
5630  if( *line != '=' )
5631  {
5632  MSG_ERROR( std::cerr << "Error parsing setting string: no '=' after parameter name.\n" );
5633  return false;
5634  }
5635  line++;
5636  }
5637 
5638  // find the start of the parameter value string
5639  while( *line == ' ' || *line == '\t' || *line == '\r' )
5640  line++;
5641  if( *line == '\0' || *line == '\n' || *line == '#' )
5642  {
5643  MSG_ERROR( std::cerr << "Error parsing setting string: no parameter value.\n");
5644  return false;
5645  }
5646  char* paramValueString = line;
5647 
5648  // find the end of the parameter value string
5649  while( *line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' && *line != '\0' )
5650  line++;
5651  if( *line != '\0' )
5652  {
5653  // check, if the rest of the line is clean
5654  *line = '\0';
5655  line++;
5656  while( *line == ' ' || *line == '\t' || *line == '\r' )
5657  line++;
5658  if( *line != '\0' && *line != '\n' && *line != '#' )
5659  {
5660  MSG_ERROR( std::cerr << "Error parsing setting string: additional character '" << *line << "' after parameter value.\n" );
5661  return false;
5662  }
5663  }
5664 
5665  // check whether we have a bool parameter
5666  if( strncmp(paramTypeString, "bool", 4) == 0 )
5667  {
5668  for( int param = 0; ; param++ )
5669  {
5670  if( param >= SoPlex::BOOLPARAM_COUNT )
5671  {
5672  MSG_ERROR( std::cerr << "Error parsing setting string: unknown parameter name <" << paramName << ">.\n" );
5673  return false;
5674  }
5675  else if( strncmp(paramName, _currentSettings->_boolParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
5676  {
5677  if( strncasecmp(paramValueString, "true", 4) == 0
5678  || strncasecmp(paramValueString, "TRUE", 4) == 0
5679  || strncasecmp(paramValueString, "t", 4) == 0
5680  || strncasecmp(paramValueString, "T", 4) == 0
5681  || strtol(paramValueString, NULL, 4) == 1 )
5682  {
5683  setBoolParam((SoPlex::BoolParam)param, true);
5684  break;
5685  }
5686  else if( strncasecmp(paramValueString, "false", 5) == 0
5687  || strncasecmp(paramValueString, "FALSE", 5) == 0
5688  || strncasecmp(paramValueString, "f", 5) == 0
5689  || strncasecmp(paramValueString, "F", 5) == 0
5690  || strtol(paramValueString, NULL, 5) == 0 )
5691  {
5692  setBoolParam((SoPlex::BoolParam)param, false);
5693  break;
5694  }
5695  else
5696  {
5697  MSG_ERROR( std::cerr << "Error parsing setting string: invalid value <" << paramValueString << "> for bool parameter <" << paramName << ">.\n" );
5698  return false;
5699  }
5700  }
5701  }
5702 
5703  return true;
5704  }
5705 
5706  // check whether we have an integer parameter
5707  if( strncmp(paramTypeString, "int", 3) == 0 )
5708  {
5709  for( int param = 0; ; param++ )
5710  {
5711  if( param >= SoPlex::INTPARAM_COUNT )
5712  {
5713  MSG_ERROR( std::cerr << "Error parsing setting string: unknown parameter name <" << paramName << ">.\n" );
5714  return false;
5715  }
5716  else if( strncmp(paramName, _currentSettings->_intParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
5717  {
5718  int value;
5719 
5720  if( sscanf(paramValueString, "%d", &value) == 1 && setIntParam((SoPlex::IntParam)param, value) )
5721  break;
5722  else
5723  {
5724  MSG_ERROR( std::cerr << "Error parsing setting string: invalid value <" << paramValueString << "> for int parameter <" << paramName << ">.\n" );
5725  return false;
5726  }
5727  }
5728  }
5729 
5730  return true;
5731  }
5732 
5733  // check whether we have a real parameter
5734  if( strncmp(paramTypeString, "real", 4) == 0 )
5735  {
5736  for( int param = 0; ; param++ )
5737  {
5738  if( param >= SoPlex::REALPARAM_COUNT )
5739  {
5740  MSG_ERROR( std::cerr << "Error parsing setting string: unknown parameter name <" << paramName << ">.\n" );
5741  return false;
5742  }
5743  else if( strncmp(paramName, _currentSettings->_realParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
5744  {
5745  Real value;
5746 
5747  if( sscanf(paramValueString, "%" REAL_FORMAT, &value) == 1 && setRealParam((SoPlex::RealParam)param, value) )
5748  break;
5749  else
5750  {
5751  MSG_ERROR( std::cerr << "Error parsing setting string: invalid value <" << paramValueString << "> for real parameter <" << paramName << ">.\n" );
5752  return false;
5753  }
5754  }
5755  }
5756 
5757  return true;
5758  }
5759 
5760 #ifdef SOPLEX_WITH_RATIONALPARAM
5761  // check whether we have a rational parameter
5762  if( strncmp(paramTypeString, "rational", 8) == 0 )
5763  {
5764  for( int param = 0; ; param++ )
5765  {
5766  if( param >= SoPlex::RATIONALPARAM_COUNT )
5767  {
5768  MSG_ERROR( std::cerr << "Error parsing setting string: unknown parameter name <" << paramName << ">.\n" );
5769  return false;
5770  }
5771  else if( strncmp(paramName, _currentSettings->_rationalParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
5772  {
5773  Rational value;
5774 
5775  if( readStringRational(paramValueString, value) && setRationalParam((SoPlex::RationalParam)param, value) )
5776  break;
5777  else
5778  {
5779  MSG_ERROR( std::cerr << "Error parsing setting string: invalid value <" << paramValueString << "> for rational parameter <" << paramName << ">.\n" );
5780  return false;
5781  }
5782  }
5783  }
5784 
5785  return true;
5786  }
5787 #endif
5788 
5789  MSG_ERROR( std::cerr << "Error parsing setting string: invalid parameter type <" << paramTypeString << "> for parameter <" << paramName << ">.\n" );
5790 
5791  return false;
5792  }
5793 
5794 
5795 
5796 
5797  /// prints solution statistics
5798  void SoPlex::printSolutionStatistics(std::ostream& os)
5799  {
5801  {
5802  os << std::scientific << std::setprecision(8)
5803  << "Solution (real) : \n"
5804  << " Objective Value : " << objValueReal() << "\n";
5805  }
5806  else if( _lastSolveMode == SOLVEMODE_RATIONAL )
5807  {
5808  os << "Solution (rational) : \n"
5809  << " Objective value : " << rationalToString(objValueRational()) << "\n";
5810  os << "Size (base 2/10) : \n"
5811  << " Total primal : " << totalSizePrimalRational() << " / " << totalSizePrimalRational(10) << "\n"
5812  << " Total dual : " << totalSizeDualRational() << " / " << totalSizeDualRational(10) << "\n"
5813  << " DLCM primal : " << dlcmSizePrimalRational() << " / " << dlcmSizePrimalRational(10) << "\n"
5814  << " DLCM dual : " << dlcmSizeDualRational() << " / " << dlcmSizeDualRational(10) << "\n"
5815  << " DMAX primal : " << dmaxSizePrimalRational() << " / " << dmaxSizePrimalRational(10) << "\n"
5816  << " DMAX dual : " << dmaxSizeDualRational() << " / " << dmaxSizeDualRational(10) << "\n";
5817  }
5818  else
5819  {
5820  os << "Solution : \n"
5821  << " Objective value : -\n";
5822  }
5823 
5826  {
5827  Rational maxviol;
5828  Rational sumviol;
5829 
5830  os << "Violation (rational): \n";
5831  if( getBoundViolationRational(maxviol, sumviol) )
5832  os << " Max/sum bound : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5833  else
5834  os << " Max/sum bound : - / -\n";
5835  if( getRowViolationRational(maxviol, sumviol) )
5836  os << " Max/sum row : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5837  else
5838  os << " Max/sum row : - / -\n";
5839  if( getRedCostViolationRational(maxviol, sumviol) )
5840  os << " Max/sum redcost : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5841  else
5842  os << " Max/sum redcost : - / -\n";
5843  if( getDualViolationRational(maxviol, sumviol) )
5844  os << " Max/sum dual : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5845  else
5846  os << " Max/sum dual : - / -\n";
5847  }
5848  else
5849  {
5850  Real maxviol;
5851  Real sumviol;
5852 
5853  os << "Violations (real) : \n";
5854  if( getBoundViolationReal(maxviol, sumviol) )
5855  os << " Max/sum bound : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5856  else
5857  os << " Max/sum bound : - / -\n";
5858  if( getRowViolationReal(maxviol, sumviol) )
5859  os << " Max/sum row : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5860  else
5861  os << " Max/sum row : - / -\n";
5862  if( getRedCostViolationReal(maxviol, sumviol) )
5863  os << " Max/sum redcost : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5864  else
5865  os << " Max/sum redcost : - / -\n";
5866  if( getDualViolationReal(maxviol, sumviol) )
5867  os << " Max/sum dual : " << rationalToString(maxviol) << " / " << rationalToString(sumviol) << "\n";
5868  else
5869  os << " Max/sum dual : - / -\n";
5870  }
5871  }
5872 
5873 
5874 
5875  /// prints statistics on solving process
5876  void SoPlex::printSolvingStatistics(std::ostream& os)
5877  {
5878  assert(_statistics != 0);
5879  _statistics->print(os);
5880  }
5881 
5882 
5883 
5884  /// prints short statistics
5885  void SoPlex::printShortStatistics(std::ostream& os)
5886  {
5887  printStatus(os, _status);
5888  os << "Solving time (sec) : " << std::fixed << std::setprecision(2) << _statistics->solvingTime->time() << "\n"
5889  << "Iterations : " << _statistics->iterations << "\n"
5890  << "Objective value : " << std::scientific << std::setprecision(8) << objValueReal() << std::fixed << "\n";
5891  }
5892 
5893 
5894 
5895  /// prints complete statistics
5896  void SoPlex::printStatistics(std::ostream& os)
5897  {
5898  os << std::setprecision(2);
5899 
5900  printStatus(os, _status);
5901 
5902  os << "Original problem : \n";
5905  else
5907 
5908  os << "Objective sense : " << (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE ? "minimize\n" : "maximize\n");
5911  }
5912 
5913 
5914 
5915  /// prints status
5916  void SoPlex::printStatus(std::ostream& os, SPxSolver::Status stat)
5917  {
5918  os << "SoPlex status : ";
5919 
5920  switch( stat )
5921  {
5922  case SPxSolver::ERROR:
5923  os << "error [unspecified]";
5924  break;
5926  os << "error [no ratiotester loaded]";
5927  break;
5928  case SPxSolver::NO_PRICER:
5929  os << "error [no pricer loaded]";
5930  break;
5931  case SPxSolver::NO_SOLVER:
5932  os << "error [no linear solver loaded]";
5933  break;
5934  case SPxSolver::NOT_INIT:
5935  os << "error [not initialized]";
5936  break;
5938  os << "solving aborted [cycling]";
5939  break;
5940  case SPxSolver::ABORT_TIME:
5941  os << "solving aborted [time limit reached]";
5942  break;
5943  case SPxSolver::ABORT_ITER:
5944  os << "solving aborted [iteration limit reached]";
5945  break;
5947  os << "solving aborted [objective limit reached]";
5948  break;
5949  case SPxSolver::NO_PROBLEM:
5950  os << "no problem loaded";
5951  break;
5952  case SPxSolver::REGULAR:
5953  os << "basis is regular";
5954  break;
5955  case SPxSolver::SINGULAR:
5956  os << "basis is singular";
5957  break;
5958  case SPxSolver::OPTIMAL:
5959  os << "problem is solved [optimal]";
5960  break;
5961  case SPxSolver::UNBOUNDED:
5962  os << "problem is solved [unbounded]";
5963  break;
5964  case SPxSolver::INFEASIBLE:
5965  os << "problem is solved [infeasible]";
5966  break;
5967  case SPxSolver::INForUNBD:
5968  os << "problem is solved [infeasible or unbounded]";
5969  break;
5970  default:
5971  case SPxSolver::UNKNOWN:
5972  os << "unknown";
5973  break;
5974  }
5975 
5976  os << "\n";
5977  }
5978 
5979 
5980 
5981  /// prints version and compilation options
5983  {
5984  // do not use preprocessor directives within the MSG_INFO1 macro
5985 #if (SOPLEX_SUBVERSION > 0)
5986  MSG_INFO1( spxout, spxout << "SoPlex version " << SOPLEX_VERSION/100
5987  << "." << (SOPLEX_VERSION % 100)/10
5988  << "." << SOPLEX_VERSION % 10
5989  << "." << SOPLEX_SUBVERSION );
5990 #else
5991  MSG_INFO1( spxout, spxout << "SoPlex version " << SOPLEX_VERSION/100
5992  << "." << (SOPLEX_VERSION % 100)/10
5993  << "." << SOPLEX_VERSION % 10 );
5994 #endif
5995 
5996 #ifndef NDEBUG
5997  MSG_INFO1( spxout, spxout << " [mode: debug]" );
5998 #else
5999  MSG_INFO1( spxout, spxout << " [mode: optimized]" );
6000 #endif
6001 
6002  MSG_INFO1( spxout, spxout << " [precision: " << (int)sizeof(Real) << " byte]" );
6003 
6004 #ifdef SOPLEX_WITH_GMP
6005 #ifdef mpir_version
6006  MSG_INFO1( spxout, spxout << " [rational: MPIR " << mpir_version << "]" );
6007 #else
6008  MSG_INFO1( spxout, spxout << " [rational: GMP " << gmp_version << "]" );
6009 #endif
6010 #else
6011  MSG_INFO1( spxout, spxout << " [rational: long double]" );
6012 #endif
6013 
6014  MSG_INFO1( spxout, spxout << " [githash: " << getGitHash() << "]\n" );
6015  }
6016 
6017 
6018 
6019  /// checks if real LP and rational LP are in sync; dimensions will always be compared,
6020  /// vector and matrix values only if the respective parameter is set to true.
6021  /// If quiet is set to true the function will only display which vectors are different.
6022  bool SoPlex::areLPsInSync(const bool checkVecVals, const bool checkMatVals, const bool quiet) const
6023  {
6024  bool result = true;
6025  bool nRowsMatch = true;
6026  bool nColsMatch = true;
6027  bool rhsDimMatch = true;
6028  bool lhsDimMatch = true;
6029  bool maxObjDimMatch = true;
6030  bool upperDimMatch = true;
6031  bool lowerDimMatch = true;
6032 
6033  // compare number of Rows
6034  if( _realLP->nRows() != _rationalLP->nRows() )
6035  {
6036  MSG_ERROR( std::cerr << "The number of Rows in the Real LP does not match the one in the Rational LP."
6037  << " Real LP: " << _realLP->nRows() << " Rational LP: " << _rationalLP->nRows() << std::endl);
6038  result = false;
6039  nRowsMatch = false;
6040  }
6041 
6042  // compare number of Columns
6043  if( _realLP->nCols() != _rationalLP->nCols() )
6044  {
6045  MSG_ERROR( std::cerr << "The number of Columns in the Real LP does not match the one in the Rational LP."
6046  << " Real LP: " << _realLP->nCols() << " Rational LP: " << _rationalLP->nCols() << std::endl);
6047  result = false;
6048  nColsMatch = false;
6049  }
6050 
6051  // compare number of nonZeros
6052  if( _realLP->nNzos() != _rationalLP->nNzos() )
6053  {
6054  MSG_ERROR( std::cerr << "The number of nonZeros in the Real LP does not match the one in the Rational LP."
6055  << " Real LP: " << _realLP->nNzos() << " Rational LP: " << _rationalLP->nNzos() << std::endl);
6056  result = false;
6057  }
6058 
6059  // compare the dimensions of the right hand side vectors
6060  if( _realLP->rhs().dim() != _rationalLP->rhs().dim() )
6061  {
6062  MSG_ERROR( std::cerr << "The dimension of the right hand side vector of the Real LP does not match the one of the Rational LP."
6063  << " Real LP: " << _realLP->rhs().dim() << " Rational LP: " << _rationalLP->rhs().dim() << std::endl);
6064  result = false;
6065  rhsDimMatch = false;
6066 
6067  }
6068 
6069  // compare the dimensions of the left hand side vectors
6070  if( _realLP->lhs().dim() != _rationalLP->lhs().dim() )
6071  {
6072  MSG_ERROR( std::cerr << "The dimension of the left hand side vector of the Real LP does not match the one of the Rational LP."
6073  << " Real LP: " << _realLP->lhs().dim() << " Rational LP: " << _rationalLP->lhs().dim() << std::endl);
6074  result = false;
6075  lhsDimMatch = false;
6076  }
6077 
6078  // compare the dimensions of the objective function vectors
6079  if( _realLP->maxObj().dim() != _rationalLP->maxObj().dim() )
6080  {
6081  MSG_ERROR( std::cerr << "The dimension of the objective function vector of the Real LP does not match the one of the Rational LP."
6082  << " Real LP: " << _realLP->maxObj().dim() << " Rational LP: " << _rationalLP->maxObj().dim() << std::endl);
6083  result = false;
6084  maxObjDimMatch = false;
6085  }
6086 
6087  // compare the sense
6088  if( (int)_realLP->spxSense() != (int)_rationalLP->spxSense() )
6089  {
6090  MSG_ERROR( std::cerr << "The objective function sense of the Real LP does not match the one of the Rational LP."
6091  << " Real LP: " << (_realLP->spxSense() == SPxLPReal::MINIMIZE ? "MIN" : "MAX")
6092  << " Rational LP: " << (_rationalLP->spxSense() == SPxLPRational::MINIMIZE ? "MIN" : "MAX") << std::endl);
6093  result = false;
6094  }
6095 
6096  // compare the dimensions of upper bound vectors
6097  if( _realLP->upper().dim() != _rationalLP->upper().dim() )
6098  {
6099  MSG_ERROR( std::cerr << "The dimension of the upper bound vector of the Real LP does not match the one of the Rational LP."
6100  << " Real LP: " << _realLP->upper().dim() << " Rational LP: " << _rationalLP->upper().dim() << std::endl);
6101  result = false;
6102  upperDimMatch = false;
6103  }
6104 
6105  // compare the dimensions of the objective function vectors
6106  if( _realLP->lower().dim() != _rationalLP->lower().dim() )
6107  {
6108  MSG_ERROR( std::cerr << "The dimension of the lower bound vector of the Real LP does not match the one of the Rational LP."
6109  << " Real LP: " << _realLP->lower().dim() << " Rational LP: " << _rationalLP->lower().dim() << std::endl);
6110  result = false;
6111  lowerDimMatch = false;
6112  }
6113 
6114  // compares the values of the rhs, lhs, maxObj, upper, lower vectors
6115  if( checkVecVals )
6116  {
6117  bool rhsValMatch = true;
6118  bool lhsValMatch = true;
6119  bool maxObjValMatch = true;
6120  bool upperValMatch = true;
6121  bool lowerValMatch = true;
6122 
6123  // compares the values of the right hand side vectors
6124  if( rhsDimMatch )
6125  {
6126  for( int i = 0; i < _realLP->rhs().dim(); i++ )
6127  {
6128  if( (GE(_realLP->rhs()[i], realParam(SoPlex::INFTY)) != (_rationalLP->rhs()[i] >= _rationalPosInfty))
6130  && !_rationalLP->rhs()[i].isAdjacentTo((double)_realLP->rhs()[i])) )
6131  {
6132  if( !quiet )
6133  {
6134  MSG_ERROR( std::cerr << "Entries number " << i << " of the right hand side vectors don't match."
6135  << " Real LP: " << _realLP->rhs()[i] << " Rational LP: " << _rationalLP->rhs()[i] << std::endl);
6136  }
6137  rhsValMatch = false;
6138  result = false;
6139  }
6140  }
6141 
6142  if( !rhsValMatch && quiet )
6143  {
6144  MSG_ERROR( std::cerr << "The values of the right hand side vectors don't match." << std::endl );
6145  }
6146  }
6147 
6148  // compares the values of the left hand side vectors
6149  if( lhsDimMatch )
6150  {
6151  for( int i = 0; i < _realLP->lhs().dim(); i++ )
6152  {
6153  if( (LE(_realLP->lhs()[i], -realParam(SoPlex::INFTY)) != (_rationalLP->lhs()[i] <= _rationalNegInfty))
6155  && !_rationalLP->lhs()[i].isAdjacentTo((double)_realLP->lhs()[i])) )
6156  {
6157  if( !quiet )
6158  {
6159  MSG_ERROR( std::cerr << "Entries number " << i << " of the left hand side vectors don't match."
6160  << " Real LP: " << _realLP->lhs()[i] << " Rational LP: " << _rationalLP->lhs()[i] << std::endl);
6161  }
6162  lhsValMatch = false;
6163  result = false;
6164  }
6165  }
6166 
6167  if( !lhsValMatch && quiet )
6168  {
6169  MSG_ERROR( std::cerr << "The values of the left hand side vectors don't match." << std::endl );
6170  }
6171  }
6172 
6173  // compares the values of the objective function vectors
6174  if( maxObjDimMatch )
6175  {
6176  for( int i = 0; i < _realLP->maxObj().dim(); i++ )
6177  {
6178  if( !_rationalLP->maxObj()[i].isAdjacentTo((double)_realLP->maxObj()[i]) )
6179  {
6180  if( !quiet )
6181  {
6182  MSG_ERROR( std::cerr << "Entries number " << i << " of the objective function vectors don't match."
6183  << " Real LP: " << _realLP->maxObj()[i] << " Rational LP: " << _rationalLP->maxObj()[i] << std::endl);
6184  }
6185  maxObjValMatch = false;
6186  result = false;
6187  }
6188  }
6189 
6190  if( !maxObjValMatch && quiet )
6191  {
6192  MSG_ERROR( std::cerr << "The values of the objective function vectors don't match." << std::endl );
6193  }
6194  }
6195 
6196  // compares the values of the upper bound vectors
6197  if( upperDimMatch )
6198  {
6199  for( int i = 0; i < _realLP->upper().dim(); i++ )
6200  {
6203  && !_rationalLP->upper()[i].isAdjacentTo((double)_realLP->upper()[i])) )
6204  {
6205  if( !quiet )
6206  {
6207  MSG_ERROR( std::cerr << "Entries number " << i << " of the upper bound vectors don't match."
6208  << " Real LP: " << _realLP->upper()[i] << " Rational LP: " << _rationalLP->upper()[i] << std::endl);
6209  }
6210  upperValMatch = false;
6211  result = false;
6212  }
6213  }
6214 
6215  if( !upperValMatch && quiet )
6216  {
6217  MSG_ERROR( std::cerr << "The values of the upper bound vectors don't match." << std::endl );
6218  }
6219  }
6220 
6221  // compares the values of the lower bound vectors
6222  if( lowerDimMatch )
6223  {
6224  for( int i = 0; i < _realLP->lower().dim(); i++ )
6225  {
6228  && !_rationalLP->lower()[i].isAdjacentTo((double)_realLP->lower()[i])) )
6229  {
6230  if( !quiet )
6231  {
6232  MSG_ERROR( std::cerr << "Entries number " << i << " of the lower bound vectors don't match."
6233  << " Real LP: " << _realLP->lower()[i] << " Rational LP: " << _rationalLP->lower()[i] << std::endl);
6234  }
6235  lowerValMatch = false;
6236  result = false;
6237  }
6238  }
6239 
6240  if( !lowerValMatch && quiet )
6241  {
6242  MSG_ERROR( std::cerr << "The values of the lower bound vectors don't match." << std::endl );
6243  }
6244  }
6245  }
6246 
6247  // compare the values of the matrix
6248  if( checkMatVals && nRowsMatch && nColsMatch )
6249  {
6250  bool matrixValMatch = true;
6251 
6252  for( int i = 0; i < _realLP->nCols() ; i++ )
6253  {
6254  for( int j = 0;j < _realLP->nRows() ; j++ )
6255  {
6256  if( !_rationalLP->colVector(i)[j].isAdjacentTo((double)_realLP->colVector(i)[j]) )
6257  {
6258  if( !quiet )
6259  {
6260  MSG_ERROR( std::cerr << "Entries number " << j << " of column number " << i << " don't match."
6261  << " Real LP: " << _realLP->colVector(i)[j] << " Rational LP: " << _rationalLP->colVector(i)[j] << std::endl);
6262  }
6263  matrixValMatch = false;
6264  result = false;
6265  }
6266  }
6267  }
6268 
6269  if( !matrixValMatch && quiet )
6270  {
6271  MSG_ERROR( std::cerr << "The values of the matrices don't match." << std::endl );
6272  }
6273  }
6274 
6275  return result;
6276  }
6277 
6278 
6279 
6280  /// extends sparse vector to hold newmax entries if and only if it holds no more free entries
6281  void SoPlex::_ensureDSVectorRationalMemory(DSVectorRational& vec, const int newmax) const
6282  {
6283  assert(newmax > vec.size());
6284  if( vec.size() >= vec.max() )
6285  vec.setMax(newmax);
6286  }
6287 
6288 
6289 
6290  /// creates a permutation for removing rows/columns from an array of indices
6291  void SoPlex::_idxToPerm(int* idx, int idxSize, int* perm, int permSize) const
6292  {
6293  assert(idx != 0);
6294  assert(idxSize >= 0);
6295  assert(perm != 0);
6296  assert(permSize >= 0);
6297 
6298  for( int i = 0; i < permSize; i++ )
6299  perm[i] = i;
6300 
6301  for( int i = 0; i < idxSize; i++ )
6302  {
6303  assert(idx[i] >= 0);
6304  assert(idx[i] < permSize);
6305  perm[idx[i]] = -1;
6306  }
6307  }
6308 
6309 
6310 
6311  /// creates a permutation for removing rows/columns from a range of indices
6312  void SoPlex::_rangeToPerm(int start, int end, int* perm, int permSize) const
6313  {
6314  assert(perm != 0);
6315  assert(permSize >= 0);
6316 
6317  for( int i = 0; i < permSize; i++ )
6318  perm[i] = (i < start || i > end) ? i : -1;
6319  }
6320 
6321 
6322 
6323  /// checks consistency
6325  {
6326  assert(_statistics != 0);
6327  assert(_currentSettings != 0);
6328 
6329  assert(_realLP != 0);
6331 
6332  assert(_realLP != &_solver || _isRealLPLoaded);
6333  assert(_realLP == &_solver || !_isRealLPLoaded);
6334 
6335  assert(!_hasBasis || _isRealLPLoaded || _basisStatusRows.size() == numRowsReal());
6336  assert(!_hasBasis || _isRealLPLoaded || _basisStatusCols.size() == numColsReal());
6337 
6338  return true;
6339  }
6340 
6341 
6342 
6343  /// should solving process be stopped?
6345  {
6346  assert(_statistics != 0);
6347 
6352  }
6353 
6354 
6355 
6356  /// determines RangeType from real bounds
6357  SoPlex::RangeType SoPlex::_rangeTypeReal(const Real& lower, const Real& upper) const
6358  {
6359  assert(lower <= upper);
6360 
6361  if( lower <= -infinity )
6362  {
6363  if( upper >= infinity )
6364  return RANGETYPE_FREE;
6365  else
6366  return RANGETYPE_UPPER;
6367  }
6368  else
6369  {
6370  if( upper >= infinity )
6371  return RANGETYPE_LOWER;
6372  else if( lower == upper )
6373  return RANGETYPE_FIXED;
6374  else
6375  return RANGETYPE_BOXED;
6376  }
6377  }
6378 
6379 
6380 
6381  /// determines RangeType from rational bounds
6383  {
6384  assert(lower <= upper);
6385 
6386  if( lower <= _rationalNegInfty )
6387  {
6388  if( upper >= _rationalPosInfty )
6389  return RANGETYPE_FREE;
6390  else
6391  return RANGETYPE_UPPER;
6392  }
6393  else
6394  {
6395  if( upper >= _rationalPosInfty )
6396  return RANGETYPE_LOWER;
6397  else if( lower == upper )
6398  return RANGETYPE_FIXED;
6399  else
6400  return RANGETYPE_BOXED;
6401  }
6402  }
6403 
6404 
6405 
6406  /// switches RANGETYPE_LOWER to RANGETYPE_UPPER and vice versa
6408  {
6409  if( rangeType == RANGETYPE_LOWER )
6410  return RANGETYPE_UPPER;
6411  else if( rangeType == RANGETYPE_UPPER )
6412  return RANGETYPE_LOWER;
6413  else
6414  return rangeType;
6415  }
6416 
6417 
6418 
6419  /// checks whether RangeType corresponds to finite lower bound
6420  bool SoPlex::_lowerFinite(const RangeType& rangeType) const
6421  {
6422  return (rangeType == RANGETYPE_LOWER || rangeType == RANGETYPE_BOXED || rangeType == RANGETYPE_FIXED);
6423  }
6424 
6425 
6426 
6427  /// checks whether RangeType corresponds to finite upper bound
6428  bool SoPlex::_upperFinite(const RangeType& rangeType) const
6429  {
6430  return (rangeType == RANGETYPE_UPPER || rangeType == RANGETYPE_BOXED || rangeType == RANGETYPE_FIXED);
6431  }
6432 
6433 
6434 
6435  /// adds a single row to the real LP and adjusts basis
6436  void SoPlex::_addRowReal(const LPRowReal& lprow)
6437  {
6438  assert(_realLP != 0);
6439 
6440  _realLP->addRow(lprow);
6441 
6442  if( _isRealLPLoaded )
6444  else if( _hasBasis )
6446  }
6447 
6448 
6449 
6450  /// adds a single row to the real LP and adjusts basis
6451  void SoPlex::_addRowReal(Real lhs, const SVectorReal& lprow, Real rhs)
6452  {
6453  assert(_realLP != 0);
6454 
6455  _realLP->addRow(lhs, lprow, rhs);
6456 
6457  if( _isRealLPLoaded )
6459  else if( _hasBasis )
6461  }
6462 
6463 
6464 
6465  /// adds multiple rows to the real LP and adjusts basis
6466  void SoPlex::_addRowsReal(const LPRowSetReal& lprowset)
6467  {
6468  assert(_realLP != 0);
6469 
6470  _realLP->addRows(lprowset);
6471 
6472  if( _isRealLPLoaded )
6474  else if( _hasBasis )
6475  _basisStatusRows.append(lprowset.num(), SPxSolver::BASIC);
6476  }
6477 
6478 
6479  /// adds a single column to the real LP and adjusts basis
6480  void SoPlex::_addColReal(const LPColReal& lpcol)
6481  {
6482  assert(_realLP != 0);
6483 
6484  _realLP->addCol(lpcol);
6485 
6486  if( _isRealLPLoaded )
6488  else if( _hasBasis )
6489  {
6490  if( lpcol.lower() > -realParam(SoPlex::INFTY) )
6492  else if( lpcol.upper() < realParam(SoPlex::INFTY) )
6494  else
6496  }
6497  }
6498 
6499 
6500 
6501  /// adds a single column to the real LP and adjusts basis
6502  void SoPlex::_addColReal(Real obj, Real lower, const SVectorReal& lpcol, Real upper)
6503  {
6504  assert(_realLP != 0);
6505 
6506  _realLP->addCol(obj, lower, lpcol, upper);
6507 
6508  if( _isRealLPLoaded )
6510  else if( _hasBasis )
6512  }
6513 
6514 
6515 
6516  /// adds multiple columns to the real LP and adjusts basis
6517  void SoPlex::_addColsReal(const LPColSetReal& lpcolset)
6518  {
6519  assert(_realLP != 0);
6520 
6521  _realLP->addCols(lpcolset);
6522 
6523  if( _isRealLPLoaded )
6525  else if( _hasBasis )
6526  {
6527  for( int i = 0; i < lpcolset.num(); i++ )
6528  {
6529  if( lpcolset.lower(i) > -realParam(SoPlex::INFTY) )
6531  else if( lpcolset.upper(i) < realParam(SoPlex::INFTY) )
6533  else
6535  }
6536  }
6537  }
6538 
6539 
6540  /// replaces row \p i with \p lprow and adjusts basis
6541  void SoPlex::_changeRowReal(int i, const LPRowReal& lprow)
6542  {
6543  assert(_realLP != 0);
6544 
6545  _realLP->changeRow(i, lprow);
6546 
6547  if( _isRealLPLoaded )
6549  else if( _hasBasis )
6550  {
6552  _hasBasis = false;
6553  else if( _basisStatusRows[i] == SPxSolver::ON_LOWER && lprow.lhs() <= -realParam(SoPlex::INFTY) )
6555  else if( _basisStatusRows[i] == SPxSolver::ON_UPPER && lprow.rhs() >= realParam(SoPlex::INFTY) )
6557  }
6558  }
6559 
6560 
6561 
6562  /// changes left-hand side vector for constraints to \p lhs and adjusts basis
6564  {
6565  assert(_realLP != 0);
6566 
6567  _realLP->changeLhs(lhs);
6568 
6569  if( _isRealLPLoaded )
6571  else if( _hasBasis )
6572  {
6573  for( int i = numRowsReal() - 1; i >= 0; i-- )
6574  {
6575  if( _basisStatusRows[i] == SPxSolver::ON_LOWER && lhs[i] <= -realParam(SoPlex::INFTY) )
6577  }
6578  }
6579  }
6580 
6581 
6582 
6583  /// changes left-hand side of row \p i to \p lhs and adjusts basis
6584  void SoPlex::_changeLhsReal(int i, const Real& lhs)
6585  {
6586  assert(_realLP != 0);
6587 
6588  _realLP->changeLhs(i, lhs);
6589 
6590  if( _isRealLPLoaded )
6591  {
6593  }
6594  else if( _hasBasis && _basisStatusRows[i] == SPxSolver::ON_LOWER && lhs <= -realParam(SoPlex::INFTY) )
6596 
6597  }
6598 
6599 
6600 
6601  /// changes right-hand side vector to \p rhs and adjusts basis
6603  {
6604  assert(_realLP != 0);
6605 
6606  _realLP->changeRhs(rhs);
6607 
6608  if( _isRealLPLoaded )
6609  {
6611  }
6612  else if( _hasBasis )
6613  {
6614  for( int i = numRowsReal() - 1; i >= 0; i-- )
6615  {
6618  }
6619  }
6620  }
6621 
6622 
6623 
6624  /// changes right-hand side of row \p i to \p rhs and adjusts basis
6625  void SoPlex::_changeRhsReal(int i, const Real& rhs)
6626  {
6627  assert(_realLP != 0);
6628 
6629  _realLP->changeRhs(i, rhs);
6630 
6631  if( _isRealLPLoaded )
6632  {
6634  }
6637  }
6638 
6639 
6640 
6641  /// changes left- and right-hand side vectors and adjusts basis
6642  void SoPlex::_changeRangeReal(const VectorReal& lhs, const VectorReal& rhs)
6643  {
6644  assert(_realLP != 0);
6645 
6646  _realLP->changeRange(lhs, rhs);
6647 
6648  if( _isRealLPLoaded )
6649  {
6651  }
6652  else if( _hasBasis )
6653  {
6654  for( int i = numRowsReal() - 1; i >= 0; i-- )
6655  {
6656  if( _basisStatusRows[i] == SPxSolver::ON_LOWER && lhs[i] <= -realParam(SoPlex::INFTY) )
6658  else if( _basisStatusRows[i] == SPxSolver::ON_UPPER && rhs[i] >= realParam(SoPlex::INFTY) )
6660  }
6661  }
6662  }
6663 
6664 
6665 
6666  /// changes left- and right-hand side of row \p i and adjusts basis
6667  void SoPlex::_changeRangeReal(int i, const Real& lhs, const Real& rhs)
6668  {
6669  assert(_realLP != 0);
6670 
6671  _realLP->changeRange(i, lhs, rhs);
6672 
6673  if( _isRealLPLoaded )
6674  {
6676  }
6677  else if( _hasBasis )
6678  {
6681  else if( _basisStatusRows[i] == SPxSolver::ON_UPPER && rhs >= realParam(SoPlex::INFTY) )
6683  }
6684  }
6685 
6686 
6687 
6688  /// replaces column \p i with \p lpcol and adjusts basis
6689  void SoPlex::_changeColReal(int i, const LPColReal& lpcol)
6690  {
6691  assert(_realLP != 0);
6692 
6693  _realLP->changeCol(i, lpcol);
6694 
6695  if( _isRealLPLoaded )
6696  {
6698  }
6699  else if( _hasBasis )
6700  {
6702  _hasBasis = false;
6703  else if( _basisStatusCols[i] == SPxSolver::ON_LOWER && lpcol.lower() <= -realParam(SoPlex::INFTY) )
6705  else if( _basisStatusCols[i] == SPxSolver::ON_UPPER && lpcol.upper() >= realParam(SoPlex::INFTY) )
6707  }
6708  }
6709 
6710 
6711 
6712  /// changes vector of lower bounds to \p lower and adjusts basis
6714  {
6715  assert(_realLP != 0);
6716 
6717  _realLP->changeLower(lower);
6718 
6719  if( _isRealLPLoaded )
6720  {
6722  }
6723  else if( _hasBasis )
6724  {
6725  for( int i = numColsReal() - 1; i >= 0; i-- )
6726  {
6727  if( _basisStatusCols[i] == SPxSolver::ON_LOWER && lower[i] <= -realParam(SoPlex::INFTY) )
6729  }
6730  }
6731  }
6732 
6733 
6734 
6735  /// changes lower bound of column i to \p lower and adjusts basis
6736  void SoPlex::_changeLowerReal(int i, const Real& lower)
6737  {
6738  assert(_realLP != 0);
6739 
6740  _realLP->changeLower(i, lower);
6741 
6742  if( _isRealLPLoaded )
6743  {
6745  }
6746  else if( _hasBasis && _basisStatusCols[i] == SPxSolver::ON_LOWER && lower <= -realParam(SoPlex::INFTY) )
6748  }
6749 
6750 
6751 
6752  /// changes vector of upper bounds to \p upper and adjusts basis
6754  {
6755  assert(_realLP != 0);
6756 
6757  _realLP->changeUpper(upper);
6758 
6759  if( _isRealLPLoaded )
6760  {
6762  }
6763  else if( _hasBasis )
6764  {
6765  for( int i = numColsReal() - 1; i >= 0; i-- )
6766  {
6767  if( _basisStatusCols[i] == SPxSolver::ON_UPPER && upper[i] >= realParam(SoPlex::INFTY) )
6769  }
6770  }
6771  }
6772 
6773 
6774 
6775  /// changes \p i 'th upper bound to \p upper and adjusts basis
6776  void SoPlex::_changeUpperReal(int i, const Real& upper)
6777  {
6778  assert(_realLP != 0);
6779 
6780  _realLP->changeUpper(i, upper);
6781 
6782  if( _isRealLPLoaded )
6783  {
6785  }
6786  else if( _hasBasis && _basisStatusCols[i] == SPxSolver::ON_UPPER && upper >= realParam(SoPlex::INFTY) )
6788  }
6789 
6790 
6791 
6792  /// changes vectors of column bounds to \p lower and \p upper and adjusts basis
6793  void SoPlex::_changeBoundsReal(const VectorReal& lower, const VectorReal& upper)
6794  {
6795  assert(_realLP != 0);
6796 
6797  _realLP->changeBounds(lower, upper);
6798 
6799  if( _isRealLPLoaded )
6800  {
6802  }
6803  else if( _hasBasis )
6804  {
6805  for( int i = numColsReal() - 1; i >= 0; i-- )
6806  {
6807  if( _basisStatusCols[i] == SPxSolver::ON_LOWER && lower[i] <= -realParam(SoPlex::INFTY) )
6809  else if( _basisStatusCols[i] == SPxSolver::ON_UPPER && upper[i] >= realParam(SoPlex::INFTY) )
6811  }
6812  }
6813  }
6814 
6815 
6816 
6817  /// changes bounds of column \p i to \p lower and \p upper and adjusts basis
6818  void SoPlex::_changeBoundsReal(int i, const Real& lower, const Real& upper)
6819  {
6820  assert(_realLP != 0);
6821 
6822  _realLP->changeBounds(i, lower, upper);
6823 
6824  if( _isRealLPLoaded )
6825  {
6827  }
6828  else if( _hasBasis )
6829  {
6832  else if( _basisStatusCols[i] == SPxSolver::ON_UPPER && upper >= realParam(SoPlex::INFTY) )
6834  }
6835  }
6836 
6837 
6838 
6839  /// changes matrix entry in row \p i and column \p j to \p val and adjusts basis
6840  void SoPlex::_changeElementReal(int i, int j, const Real& val)
6841  {
6842  assert(_realLP != 0);
6843 
6844  _realLP->changeElement(i, j, val);
6845 
6846  if( _isRealLPLoaded )
6847  {
6849  }
6850  else if( _hasBasis )
6851  {
6853  _hasBasis = false;
6854  }
6855  }
6856 
6857 
6858 
6859  /// removes row \p i and adjusts basis
6861  {
6862  assert(_realLP != 0);
6863 
6864  _realLP->removeRow(i);
6865 
6866  if( _isRealLPLoaded )
6867  {
6869  }
6870  else if( _hasBasis )
6871  {
6873  _hasBasis = false;
6874  else
6875  {
6877  _basisStatusRows.removeLast();
6878  }
6879  }
6880  }
6881 
6882 
6883 
6884  /// removes all rows with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the
6885  /// new index where row \p i has been moved to; note that \p perm must point to an array of size at least
6886  /// #numRowsReal()
6887  void SoPlex::_removeRowsReal(int perm[])
6888  {
6889  assert(_realLP != 0);
6890 
6891  _realLP->removeRows(perm);
6892 
6893  if( _isRealLPLoaded )
6894  {
6896  }
6897  else if( _hasBasis )
6898  {
6899  for( int i = numRowsReal() - 1; i >= 0 && _hasBasis; i-- )
6900  {
6901  if( perm[i] < 0 && _basisStatusRows[i] != SPxSolver::BASIC )
6902  _hasBasis = false;
6903  else if( perm[i] >= 0 && perm[i] != i )
6904  {
6905  assert(perm[i] < numRowsReal());
6906  assert(perm[perm[i]] < 0);
6907 
6908  _basisStatusRows[perm[i]] = _basisStatusRows[i];
6909  }
6910  }
6911 
6912  if( _hasBasis )
6913  _basisStatusRows.reSize(numRowsReal());
6914  }
6915  }
6916 
6917 
6918 
6919  /// removes column i
6921  {
6922  assert(_realLP != 0);
6923 
6924  _realLP->removeCol(i);
6925 
6926  if( _isRealLPLoaded )
6927  {
6929  }
6930  else if( _hasBasis )
6931  {
6933  _hasBasis = false;
6934  else
6935  {
6937  _basisStatusCols.removeLast();
6938  }
6939  }
6940  }
6941 
6942 
6943 
6944  /// removes all columns with an index \p i such that \p perm[i] < 0; upon completion, \p perm[i] >= 0 indicates the
6945  /// new index where column \p i has been moved to; note that \p perm must point to an array of size at least
6946  /// #numColsReal()
6947  void SoPlex::_removeColsReal(int perm[])
6948  {
6949  assert(_realLP != 0);
6950 
6951  _realLP->removeCols(perm);
6952 
6953  if( _isRealLPLoaded )
6954  {
6956  }
6957  else if( _hasBasis )
6958  {
6959  for( int i = numColsReal() - 1; i >= 0 && _hasBasis; i-- )
6960  {
6961  if( perm[i] < 0 && _basisStatusCols[i] == SPxSolver::BASIC )
6962  _hasBasis = false;
6963  else if( perm[i] >= 0 && perm[i] != i )
6964  {
6965  assert(perm[i] < numColsReal());
6966  assert(perm[perm[i]] < 0);
6967 
6968  _basisStatusCols[perm[i]] = _basisStatusCols[i];
6969  }
6970  }
6971 
6972  if( _hasBasis )
6973  _basisStatusCols.reSize(numColsReal());
6974  }
6975  }
6976 
6977 
6978 
6979  /// invalidates solution
6981  {
6982  ///@todo maybe this should be done individually at the places when this method is called
6984 
6985  _solReal.invalidate();
6986  _hasSolReal = false;
6987 
6989  _hasSolRational = false;
6990  }
6991 
6992 
6993 
6994  /// enables simplifier and scaler
6996  {
6997  // type of simplifier
6998  switch( intParam(SoPlex::SIMPLIFIER) )
6999  {
7000  case SIMPLIFIER_OFF:
7001  _simplifier = 0;
7002  break;
7003  case SIMPLIFIER_AUTO:
7005  assert(_simplifier != 0);
7007  break;
7008  default:
7009  break;
7010  }
7011 
7012  // type of scaler
7013  switch( intParam(SoPlex::SCALER) )
7014  {
7015  case SCALER_OFF:
7016  _scaler = 0;
7017  break;
7018  case SCALER_UNIEQUI:
7020  break;
7021  case SCALER_BIEQUI:
7023  break;
7024  case SCALER_GEO1:
7025  _scaler = &_scalerGeo1;
7026  break;
7027  case SCALER_GEO8:
7028  _scaler = &_scalerGeo8;
7029  break;
7030  default:
7031  break;
7032  }
7033  }
7034 
7035 
7036 
7037  /// disables simplifier and scaler
7039  {
7040  _simplifier = 0;
7041  _scaler = 0;
7042  }
7043 
7044 
7045 
7046  /// ensures that the rational LP is available; performs no sync
7048  {
7049  if( _rationalLP == 0 )
7050  {
7054  }
7055  }
7056 
7057 
7058 
7059  /// ensures that the real LP and the basis are loaded in the solver; performs no sync
7061  {
7062  if( !_isRealLPLoaded )
7063  {
7064  assert(_realLP != &_solver);
7065 
7067  _realLP->~SPxLPReal();
7068  spx_free(_realLP);
7069  _realLP = &_solver;
7070  _isRealLPLoaded = true;
7071 
7072  if( _hasBasis )
7073  {
7074  ///@todo this should not fail even if the basis is invalid (wrong dimension or wrong number of basic
7075  /// entries); fix either in SPxSolver or in SPxBasis
7076  assert(_basisStatusRows.size() == numRowsReal());
7077  assert(_basisStatusCols.size() == numColsReal());
7078  _solver.setBasis(_basisStatusRows.get_const_ptr(), _basisStatusCols.get_const_ptr());
7080  }
7081  }
7082  }
7083 
7084 
7085 
7086  /// call floating-point solver and update statistics on iterations etc.
7088  {
7089  bool _hadBasis = _hasBasis;
7090 
7091  // set time and iteration limit
7092  if( intParam(SoPlex::ITERLIMIT) >= 0 )
7096 
7097  // ensure that tolerances are not too small
7098  if( _solver.feastol() < 1e-12 )
7099  _solver.setFeastol(1e-12);
7100  if( _solver.opttol() < 1e-12 )
7101  _solver.setOpttol(1e-12);
7102 
7103  // set correct representation
7106  && _solver.rep() != SPxSolver::COLUMN )
7107  {
7109  }
7112  &&_solver.rep() != SPxSolver::ROW )
7113  {
7115  }
7116 
7117  // set correct type
7120  && _solver.type() != SPxSolver::ENTER )
7121  {
7123  }
7126  && _solver.type() != SPxSolver::LEAVE )
7127  {
7129  }
7130 
7131  // set pricing modes
7136  _solver.hyperPricing(true);
7138  _solver.hyperPricing(false);
7139 
7140  // call floating-point solver and catch exceptions
7142  try
7143  {
7144  _solver.solve();
7145  }
7146  catch( const SPxException& E )
7147  {
7148  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> while solving real LP.\n" );
7150  }
7151  catch( ... )
7152  {
7153  MSG_ERROR( std::cerr << "Caught unknown exception while solving real LP.\n" );
7155  }
7157 
7158  // record statistics
7161  _statistics->iterationsFromBasis += _hadBasis ? _solver.iterations() : 0;
7168  }
7169 
7170 
7171 
7172  /// reads real LP in LP or MPS format from file and returns true on success; gets row names, column names, and
7173  /// integer variables if desired
7174  bool SoPlex::_readFileReal(const char* filename, NameSet* rowNames, NameSet* colNames, DIdxSet* intVars)
7175  {
7176  assert(_realLP != 0);
7177 
7178  // clear statistics
7180 
7181  // update status
7184  _hasBasis = false;
7185 
7186  // start timing
7188 
7189  // read
7190  bool success = _realLP->readFile(filename, rowNames, colNames, intVars);
7191 
7192  // stop timing
7194 
7195  if( success )
7196  {
7198  _realLP->changeObjOffset(0.0);
7199 
7200  // if sync mode is auto, we have to copy the (rounded) real LP to the rational LP; this is counted to sync time
7201  // and not to reading time
7203  _syncLPRational();
7204  }
7205  else
7206  clearLPReal();
7207 
7208  return success;
7209  }
7210 
7211 
7212 
7213  /// reads rational LP in LP or MPS format from file and returns true on success; gets row names, column names, and
7214  /// integer variables if desired
7215  bool SoPlex::_readFileRational(const char* filename, NameSet* rowNames, NameSet* colNames, DIdxSet* intVars)
7216  {
7217  // clear statistics
7219 
7220  // start timing
7222 
7223  // update status
7226  _hasBasis = false;
7227 
7228  // read
7230  bool success = _rationalLP->readFile(filename, rowNames, colNames, intVars);
7231 
7232  // stop timing
7234 
7235  if( success )
7236  {
7240 
7241  // if sync mode is auto, we have to copy the (rounded) real LP to the rational LP; this is counted to sync time
7242  // and not to reading time
7244  _syncLPReal();
7245  // if a rational LP file is read, but only the (rounded) real LP should be kept, we have to free the rational LP
7247  {
7248  _syncLPReal();
7249  _rationalLP->~SPxLPRational();
7251  }
7252  }
7253  else
7254  clearLPRational();
7255 
7256  return success;
7257  }
7258 
7259 
7260 
7261  /// recomputes range types from scratch using real LP
7263  {
7265  for( int i = 0; i < numRowsReal(); i++ )
7266  _rowTypes[i] = _rangeTypeReal(_realLP->lhs(i), _realLP->rhs(i));
7268  for( int i = 0; i < numColsReal(); i++ )
7270  }
7271 
7272 
7273 
7274  /// recomputes range types from scratch using rational LP
7276  {
7278  for( int i = 0; i < numRowsRational(); i++ )
7281  for( int i = 0; i < numColsRational(); i++ )
7283  }
7284 
7285 
7286 
7287  /// synchronizes real LP with rational LP, i.e., copies (rounded) rational LP into real LP, without looking at the sync mode
7288  void SoPlex::_syncLPReal(bool time)
7289  {
7290  // start timing
7291  if( time )
7293 
7294  // copy LP
7295  if( _isRealLPLoaded )
7297  else
7298  *_realLP = *_rationalLP;
7299 
7300  ///@todo try loading old basis
7301  _hasBasis = false;
7302 
7303  // stop timing
7304  if( time )
7306  }
7307 
7308 
7309 
7310  /// synchronizes rational LP with real LP, i.e., copies real LP to rational LP, without looking at the sync mode
7311  void SoPlex::_syncLPRational(bool time)
7312  {
7313  // start timing
7314  if( time )
7316 
7317  // copy LP
7319  *_rationalLP = *_realLP;
7321 
7322  // stop timing
7323  if( time )
7325  }
7326 
7327 
7328 
7329  /// synchronizes real solution with rational solution, i.e., copies real solution to rational solution
7331  {
7332  if( _hasSolRational && !_hasSolReal )
7333  {
7335  _hasSolReal = true;
7336  }
7337  }
7338 
7339 
7340 
7341  /// synchronizes rational solution with real solution, i.e., copies (rounded) rational solution to real solution
7343  {
7344  if( _hasSolReal && !_hasSolRational )
7345  {
7347  _hasSolRational = true;
7348  }
7349  }
7350 
7351 
7352 
7353  /// returns pointer to a constant unit vector available until destruction of the SoPlex class
7355  {
7356  assert(i >= 0);
7357 
7358  if( i < 0 )
7359  return 0;
7360  else if( i >= _unitMatrixRational.size() )
7361  _unitMatrixRational.append(i + 1 - _unitMatrixRational.size(), (UnitVectorRational*)0);
7362  assert(i < _unitMatrixRational.size());
7363 
7364  if( _unitMatrixRational[i] == 0 )
7365  {
7368  }
7369  assert(_unitMatrixRational[i] != 0);
7370 
7371  return _unitMatrixRational[i];
7372  }
7373 
7374 
7375 
7376  /// parses one line in a settings file and returns true on success; note that the string is modified
7377  bool SoPlex::_parseSettingsLine(char* line, const int lineNumber)
7378  {
7379  assert(line != 0);
7380 
7381  // find the start of the parameter type
7382  while( *line == ' ' || *line == '\t' || *line == '\r' )
7383  line++;
7384  if( *line == '\0' || *line == '\n' || *line == '#' )
7385  return true;
7386  char* paramTypeString = line;
7387 
7388  // find the end of the parameter type
7389  while( *line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' && *line != '\0' && *line != ':' )
7390  line++;
7391  if( *line == ':' )
7392  {
7393  *line = '\0';
7394  line++;
7395  }
7396  else
7397  {
7398  *line = '\0';
7399  line++;
7400 
7401  // search for the ':' char in the line
7402  while( *line == ' ' || *line == '\t' || *line == '\r' )
7403  line++;
7404  if( *line != ':' )
7405  {
7406  MSG_ERROR( std::cerr << "Error parsing settings file: no ':' separating parameter type and name in line " << lineNumber << ".\n" );
7407  return false;
7408  }
7409  line++;
7410  }
7411 
7412  // find the start of the parameter name
7413  while( *line == ' ' || *line == '\t' || *line == '\r' )
7414  line++;
7415  if( *line == '\0' || *line == '\n' || *line == '#' )
7416  {
7417  MSG_ERROR( std::cerr << "Error parsing settings file: no parameter name in line " << lineNumber << ".\n");
7418  return false;
7419  }
7420  char* paramName = line;
7421 
7422  // find the end of the parameter name
7423  while( *line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' && *line != '\0' && *line != '=' )
7424  line++;
7425  if( *line == '=' )
7426  {
7427  *line = '\0';
7428  line++;
7429  }
7430  else
7431  {
7432  *line = '\0';
7433  line++;
7434 
7435  // search for the '=' char in the line
7436  while( *line == ' ' || *line == '\t' || *line == '\r' )
7437  line++;
7438  if( *line != '=' )
7439  {
7440  MSG_ERROR( std::cerr << "Error parsing settings file: no '=' after parameter name in line " << lineNumber << ".\n" );
7441  return false;
7442  }
7443  line++;
7444  }
7445 
7446  // find the start of the parameter value string
7447  while( *line == ' ' || *line == '\t' || *line == '\r' )
7448  line++;
7449  if( *line == '\0' || *line == '\n' || *line == '#' )
7450  {
7451  MSG_ERROR( std::cerr << "Error parsing settings file: no parameter value in line " << lineNumber << ".\n");
7452  return false;
7453  }
7454  char* paramValueString = line;
7455 
7456  // find the end of the parameter value string
7457  while( *line != ' ' && *line != '\t' && *line != '\r' && *line != '\n' && *line != '#' && *line != '\0' )
7458  line++;
7459  if( *line != '\0' )
7460  {
7461  // check, if the rest of the line is clean
7462  *line = '\0';
7463  line++;
7464  while( *line == ' ' || *line == '\t' || *line == '\r' )
7465  line++;
7466  if( *line != '\0' && *line != '\n' && *line != '#' )
7467  {
7468  MSG_ERROR( std::cerr << "Error parsing settings file: additional character '" << *line << "' after parameter value in line " << lineNumber << ".\n" );
7469  return false;
7470  }
7471  }
7472 
7473  // check whether we have a bool parameter
7474  if( strncmp(paramTypeString, "bool", 4) == 0 )
7475  {
7476  for( int param = 0; ; param++ )
7477  {
7478  if( param >= SoPlex::BOOLPARAM_COUNT )
7479  {
7480  MSG_ERROR( std::cerr << "Error parsing settings file: unknown parameter name <" << paramName << "> in line " << lineNumber << ".\n" );
7481  return false;
7482  }
7483  else if( strncmp(paramName, _currentSettings->_boolParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
7484  {
7485  if( strncasecmp(paramValueString, "true", 4) == 0
7486  || strncasecmp(paramValueString, "TRUE", 4) == 0
7487  || strncasecmp(paramValueString, "t", 4) == 0
7488  || strncasecmp(paramValueString, "T", 4) == 0
7489  || strtol(paramValueString, NULL, 4) == 1 )
7490  {
7491  setBoolParam((SoPlex::BoolParam)param, true);
7492  break;
7493  }
7494  else if( strncasecmp(paramValueString, "false", 5) == 0
7495  || strncasecmp(paramValueString, "FALSE", 5) == 0
7496  || strncasecmp(paramValueString, "f", 5) == 0
7497  || strncasecmp(paramValueString, "F", 5) == 0
7498  || strtol(paramValueString, NULL, 5) == 0 )
7499  {
7500  setBoolParam((SoPlex::BoolParam)param, false);
7501  break;
7502  }
7503  else
7504  {
7505  MSG_ERROR( std::cerr << "Error parsing settings file: invalid value <" << paramValueString << "> for bool parameter <" << paramName << "> in line " << lineNumber << ".\n" );
7506  return false;
7507  }
7508  }
7509  }
7510 
7511  return true;
7512  }
7513 
7514  // check whether we have an integer parameter
7515  if( strncmp(paramTypeString, "int", 3) == 0 )
7516  {
7517  for( int param = 0; ; param++ )
7518  {
7519  if( param >= SoPlex::INTPARAM_COUNT )
7520  {
7521  MSG_ERROR( std::cerr << "Error parsing settings file: unknown parameter name <" << paramName << "> in line " << lineNumber << ".\n" );
7522  return false;
7523  }
7524  else if( strncmp(paramName, _currentSettings->_intParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
7525  {
7526  int value;
7527 
7528  if( sscanf(paramValueString, "%d", &value) == 1 && setIntParam((SoPlex::IntParam)param, value) )
7529  break;
7530  else
7531  {
7532  MSG_ERROR( std::cerr << "Error parsing settings file: invalid value <" << paramValueString << "> for int parameter <" << paramName << "> in line " << lineNumber << ".\n" );
7533  return false;
7534  }
7535  }
7536  }
7537 
7538  return true;
7539  }
7540 
7541  // check whether we have a real parameter
7542  if( strncmp(paramTypeString, "real", 4) == 0 )
7543  {
7544  for( int param = 0; ; param++ )
7545  {
7546  if( param >= SoPlex::REALPARAM_COUNT )
7547  {
7548  MSG_ERROR( std::cerr << "Error parsing settings file: unknown parameter name <" << paramName << "> in line " << lineNumber << ".\n" );
7549  return false;
7550  }
7551  else if( strncmp(paramName, _currentSettings->_realParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
7552  {
7553  Real value;
7554 
7555  if( sscanf(paramValueString, "%" REAL_FORMAT, &value) == 1 && setRealParam((SoPlex::RealParam)param, value) )
7556  break;
7557  else
7558  {
7559  MSG_ERROR( std::cerr << "Error parsing settings file: invalid value <" << paramValueString << "> for real parameter <" << paramName << "> in line " << lineNumber << ".\n" );
7560  return false;
7561  }
7562  }
7563  }
7564 
7565  return true;
7566  }
7567 
7568 #ifdef SOPLEX_WITH_RATIONALPARAM
7569  // check whether we have a rational parameter
7570  if( strncmp(paramTypeString, "rational", 8) == 0 )
7571  {
7572  for( int param = 0; ; param++ )
7573  {
7574  if( param >= SoPlex::RATIONALPARAM_COUNT )
7575  {
7576  MSG_ERROR( std::cerr << "Error parsing settings file: unknown parameter name <" << paramName << "> in line " << lineNumber << ".\n" );
7577  return false;
7578  }
7579  else if( strncmp(paramName, _currentSettings->_rationalParamName[param].c_str(), SET_MAX_LINE_LEN) == 0 )
7580  {
7581  Rational value;
7582 
7583  if( readStringRational(paramValueString, value) && setRationalParam((SoPlex::RationalParam)param, value) )
7584  break;
7585  else
7586  {
7587  MSG_ERROR( std::cerr << "Error parsing settings file: invalid value <" << paramValueString << "> for rational parameter <" << paramName << "> in line " << lineNumber << ".\n" );
7588  return false;
7589  }
7590  }
7591  }
7592 
7593  return true;
7594  }
7595 #endif
7596 
7597  MSG_ERROR( std::cerr << "Error parsing settings file: invalid parameter type <" << paramTypeString << "> for parameter <" << paramName << "> in line " << lineNumber << ".\n" );
7598 
7599  return false;
7600  }
7601 } // namespace soplex
7602 #endif