Scippy

SoPlex

Sequential object-oriented simPlex

solvereal.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-2016 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 #ifndef SOPLEX_LEGACY
17 #include <iostream>
18 #include <assert.h>
19 
20 #include "soplex.h"
21 #include "statistics.h"
22 
23 namespace soplex
24 {
25  /// solves real LP
27  {
28  // start timing
30 
31  // remember that last solve was in floating-point
33 
34  // solve and store solution; if we have a starting basis, do not apply preprocessing; if we are solving from
35  // scratch, apply preprocessing according to parameter settings
38 
39  // stop timing
41  }
42 
43 
44 
45  /// checks result of the solving process and solves again without preprocessing if necessary
47  {
48  if( simplificationStatus == SPxSimplifier::INFEASIBLE )
50  else if( simplificationStatus == SPxSimplifier::DUAL_INFEASIBLE )
52  else if( simplificationStatus == SPxSimplifier::UNBOUNDED )
54  else if( simplificationStatus == SPxSimplifier::VANISHED )
56  else if( simplificationStatus == SPxSimplifier::OKAY )
58 
59  // process result
60  switch( _status )
61  {
62  case SPxSolver::OPTIMAL:
63  if( !_isRealLPLoaded )
64  {
65  MSG_INFO1( spxout, spxout << " --- transforming basis into original space" << std::endl; )
67  _resolveWithoutPreprocessing(simplificationStatus);
68  return;
69  }
70  else
71  _hasBasis = true;
72  break;
73 
77  // in case of infeasibility or unboundedness, we currently can not unsimplify, but have to solve the original LP again
78  if( !_isRealLPLoaded )
79  {
82  return;
83  }
84  else
86  break;
87 
89  // if preprocessing was applied, try to run again without to avoid singularity
90  if( !_isRealLPLoaded )
91  {
94  return;
95  }
96  break;
97 
99  // if preprocessing was applied, try to run again without to avoid cycling
100  if( !_isRealLPLoaded )
101  {
104  return;
105  }
106  // else fallthrough
110  case SPxSolver::REGULAR:
111  case SPxSolver::RUNNING:
112  if( _isRealLPLoaded )
114  // store regular basis if there is no simplifier and the original problem is not in the solver because of
115  // scaling; non-optimal bases should currently not be unsimplified
116  else if( _simplifier == 0 && _solver.basis().status() > SPxBasis::NO_PROBLEM )
117  {
118  _basisStatusRows.reSize(numRowsReal());
119  _basisStatusCols.reSize(numColsReal());
120  assert(_basisStatusRows.size() == _solver.nRows());
121  assert(_basisStatusCols.size() == _solver.nCols());
122 
124  _hasBasis = true;
125  }
126  else
127  _hasBasis = false;
128  break;
129 
130  default:
131  _hasBasis = false;
132  break;
133  }
134  }
135 
136 
137 
138  /// solves real LP with/without preprocessing
139  void SoPlex::_preprocessAndSolveReal(bool applyPreprocessing)
140  {
143 
144  if( applyPreprocessing )
146  else
148 
151 
152  applyPreprocessing = (_simplifier != 0 || _scaler != 0);
153 
154  if( _isRealLPLoaded )
155  {
156  assert(_realLP == &_solver);
157 
158  // preprocessing is always applied to the LP in the solver; hence we have to create a copy of the original LP
159  // if preprocessing is turned on
160  if( applyPreprocessing )
161  {
162  _realLP = 0;
164  _realLP = new (_realLP) SPxLPReal(_solver);
165  _isRealLPLoaded = false;
166  }
167  }
168  else
169  {
170  assert(_realLP != &_solver);
171 
172  // ensure that the solver has the original problem
174 
175  // load basis if available
176  if( _hasBasis )
177  {
178  assert(_basisStatusRows.size() == numRowsReal());
179  assert(_basisStatusCols.size() == numColsReal());
180 
181  ///@todo this should not fail even if the basis is invalid (wrong dimension or wrong number of basic
182  /// entries); fix either in SPxSolver or in SPxBasis
183  _solver.setBasis(_basisStatusRows.get_const_ptr(), _basisStatusCols.get_const_ptr());
184  }
185 
186  // if there is no preprocessing, then the original and the transformed problem are identical and it is more
187  // memory-efficient to keep only the problem in the solver
188  if( !applyPreprocessing )
189  {
190  _realLP->~SPxLPReal();
191  spx_free(_realLP);
192  _realLP = &_solver;
193  _isRealLPLoaded = true;
194  }
195  }
196 
197  // assert that we have two problems if and only if we apply preprocessing
198  assert(_realLP == &_solver || applyPreprocessing);
199  assert(_realLP != &_solver || !applyPreprocessing);
200 
201  // apply problem simplification
202  SPxSimplifier::Result simplificationStatus = SPxSimplifier::OKAY;
203  if( _simplifier != 0 )
204  {
205  // do not remove bounds of boxed variables or sides of ranged rows if bound flipping is used
209  }
210 
212 
213  // run the simplex method if problem has not been solved by the simplifier
214  if( simplificationStatus == SPxSimplifier::OKAY )
215  {
216  if( _scaler != 0 )
218 
220  }
221 
222  // check the result and run again without preprocessing if necessary
223  _evaluateSolutionReal(simplificationStatus);
224  }
225 
226 
227 
228  /// loads original problem into solver and solves again after it has been solved to optimality with preprocessing
230  {
231  assert(!_isRealLPLoaded);
232  assert(_simplifier != 0 || _scaler != 0);
233  assert(simplificationStatus == SPxSimplifier::VANISHED
234  || (simplificationStatus == SPxSimplifier::OKAY && _solver.status() == SPxSolver::OPTIMAL));
235 
236  // if simplifier is active and LP is solved in presolving or to optimality, then we unsimplify to get the basis
237  if( _simplifier != 0 )
238  {
239  assert(!_simplifier->isUnsimplified());
240 
241  bool vanished = simplificationStatus == SPxSimplifier::VANISHED;
242 
243  // get solution vectors for transformed problem
244  DVectorReal primal(vanished ? 0 : _solver.nCols());
245  DVectorReal slacks(vanished ? 0 : _solver.nRows());
246  DVectorReal dual(vanished ? 0 : _solver.nRows());
247  DVectorReal redCost(vanished ? 0 : _solver.nCols());
248 
249  _basisStatusRows.reSize(numRowsReal());
250  _basisStatusCols.reSize(numColsReal());
251  assert(vanished || _basisStatusRows.size() >= _solver.nRows());
252  assert(vanished || _basisStatusCols.size() >= _solver.nCols());
253 
254  if( !vanished )
255  {
256  assert(_solver.status() == SPxSolver::OPTIMAL);
257 
258  _solver.getPrimal(primal);
259  _solver.getSlacks(slacks);
260  _solver.getDual(dual);
261  _solver.getRedCost(redCost);
262 
263  // unscale vectors
264  if( _scaler != 0 )
265  {
266  _scaler->unscalePrimal(primal);
267  _scaler->unscaleSlacks(slacks);
268  _scaler->unscaleDual(dual);
269  _scaler->unscaleRedCost(redCost);
270  }
271 
272  // get basis of transformed problem
274  }
275 
276  try
277  {
278  _simplifier->unsimplify(primal, dual, slacks, redCost, _basisStatusRows.get_ptr(), _basisStatusCols.get_ptr());
280  _hasBasis = true;
281  }
282  catch( const SPxException& E )
283  {
284  MSG_ERROR( std::cerr << "Caught exception <" << E.what() << "> during unsimplification. Resolving without simplifier and scaler.\n" );
285  }
286  catch( ... )
287  {
288  MSG_ERROR( std::cerr << "Caught unknown exception during unsimplification. Resolving without simplifier and scaler.\n" );
290  }
291  }
292  // if the original problem is not in the solver because of scaling, we also need to store the basis
293  else if( _scaler != 0 )
294  {
295  _basisStatusRows.reSize(numRowsReal());
296  _basisStatusCols.reSize(numColsReal());
297  assert(_basisStatusRows.size() == _solver.nRows());
298  assert(_basisStatusCols.size() == _solver.nCols());
299 
301  _hasBasis = true;
302  }
303 
304  // resolve the original problem
306  return;
307  }
308 
309 
310 
311  /// stores solution of the real LP; before calling this, the real LP must be loaded in the solver and solved (again)
313  {
314  assert(status() != SPxSolver::OPTIMAL || _isRealLPLoaded);
315 
327 
332  if( _solReal._hasPrimal )
333  {
339  }
340 
342  if( _solReal._hasPrimalRay )
343  {
346  }
347 
348  assert(_solver.basis().status() != SPxBasis::DUAL || status() != SPxSolver::ERROR);
359 
363  if( _solReal._hasDual )
364  {
370  }
371 
374  {
377  }
378 
379  _hasSolReal = true;
380  }
381 } // namespace soplex
382 #endif
virtual Real objValue()
get objective value of current solution.
Definition: spxsolver.h:1857
int _lastSolveMode
Definition: soplex.h:1429
SPxLPBase< Real > SPxLPReal
Definition: spxlp.h:36
DVectorBase< R > _slacks
Definition: solbase.h:223
int numColsReal() const
returns number of columns
Definition: soplex.cpp:779
virtual Status getPrimal(Vector &vector) const
get solution vector for primal variables.
Definition: spxsolve.cpp:1219
Basis is dual feasible.
Definition: spxbasis.h:95
virtual void scale(SPxLP &lp)=0
scale SPxLP.
not initialised error
Definition: spxsolver.h:196
void reDim(int newdim, const bool setZero=true)
Resets DVectorBase&#39;s dimension to newdim.
Definition: dvectorbase.h:249
DVectorBase< R > _dualFarkas
Definition: solbase.h:227
virtual void getBasis(SPxSolver::VarStatus[], SPxSolver::VarStatus[], const int rowsSize=-1, const int colsSize=-1) const =0
get optimal basis.
virtual void unsimplify(const Vector &, const Vector &, const Vector &, const Vector &, const SPxSolver::VarStatus[], const SPxSolver::VarStatus[])
reconstructs an optimal solution for the unsimplified LP.
virtual const std::string what() const
returns exception message
Definition: exceptions.h:57
upper limit on objective value
Definition: soplex.h:1172
general zero tolerance
Definition: soplex.h:1151
Result
Result of the simplification.
Definition: spxsimplifier.h:81
type of ratio test
Definition: soplex.h:891
virtual void unscaleSlacks(Vector &s) const
unscale dense slack vector given in s.
Definition: spxscaler.cpp:279
the problem was so much simplified that it vanished
Definition: spxsimplifier.h:87
void setBasis(const VarStatus rows[], const VarStatus cols[])
set the lp solver&#39;s basis.
Definition: spxsolver.cpp:1795
virtual Result simplify(SPxLP &lp, Real eps, Real delta)=0
simplify SPxLP lp with identical primal and dual feasibility tolerance.
apply standard floating-point algorithm
Definition: soplex.h:1093
SPxStatus status() const
returns current SPxStatus.
Definition: spxbasis.h:419
virtual Status getRedCost(Vector &vector) const
get vector of reduced costs.
Definition: spxsolve.cpp:1299
virtual bool isUnsimplified() const
specifies whether an optimal solution has already been unsimplified.
DVectorBase< R > _primalRay
Definition: solbase.h:224
DVectorBase< R > _redCost
Definition: solbase.h:226
primal feasibility tolerance
Definition: soplex.h:1145
int numRowsReal() const
message handler
Definition: soplex.cpp:770
bound flipping ratio test for long steps in the dual simplex
Definition: soplex.h:1063
solve() aborted due to iteration limit.
Definition: spxsolver.h:199
SPxScaler * _scaler
Definition: soplex.h:1356
No Problem has been loaded.
Definition: spxsolver.h:202
void _disableSimplifierAndScaler()
disables simplifier and scaler
Definition: soplex.cpp:7060
unsigned int _hasPrimalRay
Definition: solbase.h:233
objective sense
Definition: soplex.h:849
virtual void unscaleDual(Vector &pi) const
unscale dense dual solution vector given in pi.
Definition: spxscaler.cpp:296
LP has been proven to be primal infeasible.
Definition: spxsolver.h:208
virtual Real shift() const
total current shift amount.
Definition: spxsolver.h:1482
virtual void changeObjOffset(const R &o)
Definition: spxlpbase.h:1611
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:4866
void _solveReal()
solves real LP
Definition: solvereal.cpp:26
No ratiotester loaded.
Definition: spxsolver.h:193
No pricer loaded.
Definition: spxsolver.h:194
virtual void start()=0
start timer, resume accounting user, system and real time.
virtual Real stop()=0
stop timer, return accounted user time.
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
simplification could be done
Definition: spxsimplifier.h:83
LP is primal infeasible or unbounded.
Definition: spxsolver.h:209
DataArray< SPxSolver::VarStatus > _basisStatusCols
Definition: soplex.h:1432
SPxSolver::Status status() const
returns the current solver status
Definition: soplex.cpp:2799
bool _isRealLPLoaded
Definition: soplex.h:1359
virtual Status getDual(Vector &vector) const
get current solution vector for dual variables.
Definition: spxsolve.cpp:1268
void _solveRealLPAndRecordStatistics()
call floating-point solver and update statistics on iterations etc.
Definition: soplex.cpp:7109
DVectorBase< R > _primal
Definition: solbase.h:222
Status getBasis(VarStatus rows[], VarStatus cols[], const int rowsSize=-1, const int colsSize=-1) const
get current basis, and return solver status.
Definition: spxsolver.cpp:1722
LP has been solved to optimality.
Definition: spxsolver.h:206
virtual Status getPrimalray(Vector &vector) const
get primal ray in case of unboundedness.
Definition: spxsolve.cpp:1342
bool _hasBasis
Definition: soplex.h:1438
unsigned int _hasDualFarkas
Definition: solbase.h:235
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:133
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1616
Class for collecting statistical information.
solve() aborted due to time limit.
Definition: spxsolver.h:198
an error occured.
Definition: spxsolver.h:192
Statistics * _statistics
statistics since last call to solveReal() or solveRational()
Definition: soplex.h:1308
void _evaluateSolutionReal(SPxSimplifier::Result simplificationStatus)
checks result of the solving process and solves again without preprocessing if necessary ...
Definition: solvereal.cpp:46
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:109
virtual void unscalePrimal(Vector &x) const
unscale dense primal solution vector given in x.
Definition: spxscaler.cpp:262
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:113
primal infeasibility was detected
Definition: spxsimplifier.h:84
SPxOut spxout
Definition: soplex.h:1215
algorithm is running
Definition: spxsolver.h:204
Preconfigured SoPlex LP solver.
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:127
virtual void unscaleRedCost(Vector &r) const
unscale dense reduced cost vector given in r.
Definition: spxscaler.cpp:313
Timer * preprocessingTime
preprocessing time
Definition: statistics.h:90
Exception base class.This class implements a base class for our SoPlex exceptions We provide a what()...
Definition: exceptions.h:32
Everything should be within this namespace.
SPxLPReal * _realLP
Definition: soplex.h:1354
void _preprocessAndSolveReal(bool applyPreprocessing)
solves real LP with/without preprocessing
Definition: solvereal.cpp:139
solve() aborted due to detection of cycling.
Definition: spxsolver.h:197
primal unboundedness was detected
Definition: spxsimplifier.h:86
SPxSolver _solver
Definition: soplex.h:1333
void _resolveWithoutPreprocessing(SPxSimplifier::Result simplificationStatus)
loads original problem into solver and solves again after it has been solved to optimality with prepr...
Definition: solvereal.cpp:229
virtual Status getSlacks(Vector &vector) const
get vector of slack variables.
Definition: spxsolve.cpp:1378
Status status() const
Status of solution process.
Definition: spxsolve.cpp:1536
DataArray< SPxSolver::VarStatus > _basisStatusRows
Definition: soplex.h:1431
unsigned int _hasPrimal
Definition: solbase.h:232
Timer * solvingTime
solving time
Definition: statistics.h:89
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:4856
SolReal _solReal
Definition: soplex.h:1434
lower limit on objective value
Definition: soplex.h:1169
bool _hasSolReal
Definition: soplex.h:1439
virtual Status getDualfarkas(Vector &vector) const
get dual farkas proof of infeasibility.
Definition: spxsolve.cpp:1360
virtual void loadLP(const SPxLP &LP)
copy LP.
Definition: spxsolver.cpp:68
unsigned int _hasDual
Definition: solbase.h:234
dual feasibility tolerance
Definition: soplex.h:1148
void forceRecompNonbasicValue()
Definition: spxsolver.h:545
void _enableSimplifierAndScaler()
enables simplifier and scaler according to current parameters
Definition: soplex.cpp:7017
DVectorBase< R > _dual
Definition: solbase.h:225
virtual void setTerminationValue(Real value=infinity)
set objective limit.
Definition: spxsolver.cpp:1542
void _storeSolutionReal()
stores solution of the real LP; before calling this, the real LP must be loaded in the solver and sol...
Definition: solvereal.cpp:312
LP has been proven to be primal unbounded.
Definition: spxbasis.h:98
SPxSolver::Status _status
Definition: soplex.h:1428
solve() aborted due to objective limit.
Definition: spxsolver.h:200
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
SPxSimplifier * _simplifier
Definition: soplex.h:1355
Basis is singular, numerical troubles?
Definition: spxsolver.h:201
Basis is primal feasible.
Definition: spxbasis.h:96
LP has a usable Basis (maybe LP is changed).
Definition: spxsolver.h:203
virtual Real getObjoffset() const
get objective offset.
dual infeasibility was detected
Definition: spxsimplifier.h:85
LP has been proven to be primal unbounded.
Definition: spxsolver.h:207
LP has been proven to be primal infeasible.
Definition: spxbasis.h:99
No Problem has been loaded to the basis.
Definition: spxbasis.h:92
No linear solver loaded.
Definition: spxsolver.h:195