Scippy

SoPlex

Sequential object-oriented simPlex

spxchangebasis.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 #include <iostream>
17 
18 #include "spxdefines.h"
19 #include "spxbasis.h"
20 #include "spxsolver.h"
21 #include "spxout.h"
22 
23 namespace soplex
24 {
25 
27 {
28 
29  assert(theLP != 0);
30 
31  MSG_DEBUG( std::cout << "DCHBAS01 SPxBasis::reDim():"
32  << " matrixIsSetup=" << matrixIsSetup
33  << " fatorized=" << factorized
34  << std::endl; )
35 
37 
38  if (theLP->dim() != matrix.size())
39  {
40  MSG_INFO3( (*spxout), (*spxout) << "ICHBAS02 basis redimensioning invalidates factorization"
41  << std::endl; )
42 
43  matrix.reSize (theLP->dim());
44  theBaseId.reSize(theLP->dim());
45  matrixIsSetup = false;
46  factorized = false;
47  }
48 
49  MSG_DEBUG( std::cout << "DCHBAS03 SPxBasis::reDim(): -->"
50  << " matrixIsSetup=" << matrixIsSetup
51  << " fatorized=" << factorized
52  << std::endl; )
53 
54  assert( matrix.size() >= theLP->dim() );
55  assert( theBaseId.size() >= theLP->dim() );
56 }
57 
58 /* adapt basis and basis descriptor to added rows */
60 {
61  assert(theLP != 0);
62 
63  if( n > 0 )
64  {
65  reDim();
66 
67  if (theLP->rep() == SPxSolver::COLUMN)
68  {
69  /* after adding rows in column representation, reDim() should set these bools to false. */
70  assert( !matrixIsSetup && !factorized );
71 
72  for (int i = theLP->nRows() - n; i < theLP->nRows(); ++i)
73  {
75  baseId(i) = theLP->SPxLP::rId(i);
76  }
77  }
78  else
79  {
80  assert(theLP->rep() == SPxSolver::ROW);
81 
82  for (int i = theLP->nRows() - n; i < theLP->nRows(); ++i)
84  }
85 
86  /* If matrix was set up, load new basis vectors to the matrix.
87  * In the row case, the basis is not effected by adding rows. However,
88  * since @c matrix stores references to the rows in the LP (SPxLP), a realloc
89  * in SPxLP (e.g. due to space requirements) might invalidate these references.
90  * We therefore have to "reload" the matrix if it is set up. Note that reDim()
91  * leaves @c matrixIsSetup untouched if only row have been added, since the basis
92  * matrix already has the correct size. */
93  if (status() > NO_PROBLEM && matrixIsSetup)
95 
96  /* update basis status */
97  switch (status())
98  {
99  case PRIMAL:
100  case UNBOUNDED:
102  break;
103  case OPTIMAL:
104  case INFEASIBLE:
105  setStatus(DUAL);
106  break;
107  case NO_PROBLEM:
108  case SINGULAR:
109  case REGULAR:
110  case DUAL:
111  break;
112  default:
113  MSG_ERROR( std::cerr << "ECHBAS04 Unknown basis status!" << std::endl; )
114  throw SPxInternalCodeException("XCHBAS01 This should never happen.");
115  }
116  }
117 }
118 
120 {
121 
122  assert(status() > NO_PROBLEM);
123  assert(theLP != 0);
124 
125  if (theLP->rep() == SPxSolver::ROW)
126  {
127  if (theLP->isBasic(thedesc.rowStatus(i)))
128  {
130  factorized = false;
131 
132  MSG_DEBUG( std::cout << "DCHBAS05 Warning: deleting basic row!\n"; )
133  }
134  }
135  else
136  {
137  assert(theLP->rep() == SPxSolver::COLUMN);
138  factorized = false;
139  if (!theLP->isBasic(thedesc.rowStatus(i)))
140  {
142  MSG_DEBUG( std::cout << "DCHBAS06 Warning: deleting nonbasic row!\n"; )
143  }
144  else if (status() > NO_PROBLEM && matrixIsSetup)
145  {
146  for (int j = theLP->dim(); j >= 0; --j)
147  {
148  SPxId id = baseId(j);
149 
150  if (id.isSPxRowId() && theLP->number(SPxRowId(id)) < 0)
151  {
152  baseId(j) = baseId(theLP->dim());
153 
154  if (j < theLP->dim())
155  matrix[j] = &theLP->vector(baseId(j));
156  break;
157  }
158  }
159  }
160  }
162  reDim();
163 }
164 
165 void SPxBasis::removedRows(const int perm[])
166 {
167  assert(status() > NO_PROBLEM);
168  assert(theLP != 0);
169 
170  int i;
171  int n = thedesc.nRows();
172 
173  if (theLP->rep() == SPxSolver::ROW)
174  {
175  for (i = 0; i < n; ++i)
176  {
177  if (perm[i] != i)
178  {
179  if (perm[i] < 0) // row got removed
180  {
181  if (theLP->isBasic(thedesc.rowStatus(i)))
182  {
184  factorized = matrixIsSetup = false;
185  MSG_DEBUG( std::cout << "DCHBAS07 Warning: deleting basic row!\n"; )
186  }
187  }
188  else // row was moved
189  thedesc.rowStatus(perm[i]) = thedesc.rowStatus(i);
190  }
191  }
192  }
193  else
194  {
195  assert(theLP->rep() == SPxSolver::COLUMN);
196 
197  factorized = false;
198  matrixIsSetup = false;
199 
200  for (i = 0; i < n; ++i)
201  {
202  if (perm[i] != i)
203  {
204  if (perm[i] < 0) // row got removed
205  {
206  if (!theLP->isBasic(thedesc.rowStatus(i)))
208  }
209  else // row was moved
210  thedesc.rowStatus(perm[i]) = thedesc.rowStatus(i);
211  }
212  }
213  }
214  reDim();
215 }
216 
217 
220 {
221  assert(theLP != 0);
222 
223  if (theLP->upper(i) < infinity)
224  {
225  if (theLP->lower(i) > -infinity)
226  {
227  if (theLP->lower(i) == theLP->SPxLP::upper(i))
229  /*
230  else
231  return (-theLP->lower(i) < theLP->upper(i))
232  ? SPxBasis::Desc::P_ON_LOWER
233  : SPxBasis::Desc::P_ON_UPPER;
234  */
235  else if (theLP->maxObj(i) == 0)
236  return (-theLP->lower(i) < theLP->upper(i))
239  else
240  return (theLP->maxObj(i) < 0)
243  }
244  else
246  }
247  else if (theLP->lower(i) > -infinity)
249  else
250  return SPxBasis::Desc::P_FREE;
251 }
252 
253 
254 /* adapt basis and basis descriptor to added columns */
256 {
257  assert(theLP != 0);
258 
259  if( n > 0 )
260  {
261  reDim();
262 
263  if (theLP->rep() == SPxSolver::ROW)
264  {
265  /* after adding columns in row representation, reDim() should set these bools to false. */
266  assert( !matrixIsSetup && !factorized );
267 
268  for (int i = theLP->nCols() - n; i < theLP->nCols(); ++i)
269  {
271  baseId(i) = theLP->SPxLP::cId(i);
272  }
273  }
274  else
275  {
276  assert(theLP->rep() == SPxSolver::COLUMN);
277 
278  for (int i = theLP->nCols() - n; i < theLP->nCols(); ++i)
280  }
281 
282  /* If matrix was set up, load new basis vectors to the matrix
283  * In the column case, the basis is not effected by adding columns. However,
284  * since @c matrix stores references to the columns in the LP (SPxLP), a realloc
285  * in SPxLP (e.g. due to space requirements) might invalidate these references.
286  * We therefore have to "reload" the matrix if it is set up. Note that reDim()
287  * leaves @c matrixIsSetup untouched if only columns have been added, since the
288  * basis matrix already has the correct size. */
289  if (status() > NO_PROBLEM && matrixIsSetup)
290  loadMatrixVecs();
291 
292  switch (status())
293  {
294  case DUAL:
295  case INFEASIBLE:
297  break;
298  case OPTIMAL:
299  case UNBOUNDED:
300  setStatus(PRIMAL);
301  break;
302  case NO_PROBLEM:
303  case SINGULAR:
304  case REGULAR:
305  case PRIMAL:
306  break;
307  default:
308  MSG_ERROR( std::cerr << "ECHBAS08 Unknown basis status!" << std::endl; )
309  throw SPxInternalCodeException("XCHBAS02 This should never happen.");
310  }
311  }
312 }
313 
315 {
316  assert(status() > NO_PROBLEM);
317  assert(theLP != 0);
318 
319  if (theLP->rep() == SPxSolver::COLUMN)
320  {
321  if (theLP->isBasic(thedesc.colStatus(i)))
323  }
324  else
325  {
326  assert(theLP->rep() == SPxSolver::ROW);
327  factorized = false;
328  if (!theLP->isBasic(thedesc.colStatus(i)))
330  else if (status() > NO_PROBLEM)
331  {
332  for (int j = theLP->dim(); j >= 0; --j)
333  {
334  SPxId id = baseId(j);
335  if (id.isSPxColId()
336  && theLP->number(SPxColId(id)) < 0)
337  {
338  baseId(j) = baseId(theLP->dim());
339  if ( matrixIsSetup &&
340  j < theLP->dim() )
341  matrix[j] = &theLP->vector(baseId(j));
342  break;
343  }
344  }
345  }
346  }
347 
349  reDim();
350 }
351 
352 void SPxBasis::removedCols(const int perm[])
353 {
354  assert(status() > NO_PROBLEM);
355  assert(theLP != 0);
356 
357  int i;
358  int n = thedesc.nCols();
359 
360  if (theLP->rep() == SPxSolver::COLUMN)
361  {
362  for (i = 0; i < n; ++i)
363  {
364  if (perm[i] < 0) // column got removed
365  {
366  if (theLP->isBasic(thedesc.colStatus(i)))
368  }
369  else // column was potentially moved
370  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
371  }
372  }
373  else
374  {
375  assert(theLP->rep() == SPxSolver::ROW);
376  factorized = matrixIsSetup = false;
377  for (i = 0; i < n; ++i)
378  {
379  if (perm[i] != i)
380  {
381  if (perm[i] < 0) // column got removed
382  {
383  if (!theLP->isBasic(thedesc.colStatus(i)))
385  }
386  else // column was moved
387  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
388  }
389  }
390  }
391 
392  reDim();
393 }
394 
395 
396 /**
397  * mark the basis as not factorized
398  */
400 {
401  if( factorized || matrixIsSetup )
402  {
403  MSG_INFO3( (*spxout), (*spxout) << "ICHBAS09 explicit invalidation of factorization" << std::endl; )
404  }
405 
406  factorized = false;
407  matrixIsSetup = false;
408 }
409 
410 
411 /**
412  * Create the initial slack basis descriptor and set up the basis matrix accordingly.
413  * This code has been adapted from SPxBasis::addedRows() and SPxBasis::addedCols().
414  */
416 {
417  assert(!factorized);
418 
419  MSG_INFO3( (*spxout), (*spxout) << "ICHBAS10 setup slack basis" << std::endl; )
420 
421  if (theLP->rep() == SPxSolver::COLUMN)
422  {
423  for (int i = 0; i < theLP->nRows(); ++i)
424  {
426  baseId(i) = theLP->SPxLP::rId(i);
427  }
428 
429  for (int i = 0; i < theLP->nCols(); ++i)
431  }
432  else
433  {
434  assert(theLP->rep() == SPxSolver::ROW);
435 
436  for (int i = 0; i < theLP->nRows(); ++i)
438 
439  for (int i = 0; i < theLP->nCols(); ++i)
440  {
442  baseId(i) = theLP->SPxLP::cId(i);
443  }
444  }
445 
446  /* if matrix was set up, load new basis vectors to the matrix */
447  if (status() > NO_PROBLEM && matrixIsSetup)
448  loadMatrixVecs();
449 
450  /* update basis status */
452 }
453 
454 /**
455  * @todo Implement changedRow(), changedCol(), changedElement() in a more clever
456  * way. For instance, the basis won't be singular (but maybe infeasible) if the
457  * change doesn't affect the basis rows/columns.
458  *
459  * The following methods (changedRow(), changedCol(), changedElement()) radically
460  * change the current basis to the original (slack) basis also present after
461  * loading the LP. The reason is that through the changes, the current basis may
462  * become singular. Going back to the initial basis is quite inefficient, but
463  * correct.
464  */
465 
466 /**@todo is this correctly implemented?
467  */
468 void SPxBasis::changedRow(int /*row*/)
469 {
470  invalidate();
472 }
473 
474 /**@todo is this correctly implemented?
475  */
476 void SPxBasis::changedCol(int /*col*/)
477 {
478  invalidate();
480 }
481 
482 /**@todo is this correctly implemented?
483  */
484 void SPxBasis::changedElement(int /*row*/, int /*col*/)
485 {
486  invalidate();
488 }
489 } // namespace soplex
Exception class for things that should NEVER happen.This class is derived from the SoPlex exception b...
Definition: exceptions.h:109
void addedRows(int n)
inform SPxBasis, that n new rows had been added.
Basis is dual feasible.
Definition: spxbasis.h:95
Basis is not known to be dual nor primal feasible.
Definition: spxbasis.h:94
primal variable is fixed to both bounds
Definition: spxbasis.h:190
void invalidate()
invalidates actual basis.
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:456
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
void removedCols(const int perm[])
inform SPxBasis that columns in perm with negative entry were removed.
Basis is optimal, i.e. dual and primal feasible.
Definition: spxbasis.h:97
Status & rowStatus(int i)
Definition: spxbasis.h:239
void changedCol(int)
inform SPxBasis that a column had been changed.
int number(const SPxRowId &id) const
Returns the row number of the row with identifier id.
Definition: spxlpbase.h:522
static SPxBasis::Desc::Status primalColStatus(int i, const SPxLP *theLP)
int dim() const
dimension of basis matrix.
Definition: spxsolver.h:1047
void reSize(int rowDim, int colDim)
resets dimensions.
Definition: spxdesc.cpp:94
Ids for LP columns.Class SPxColId provides DataKeys for the column indices of an SPxLP.
Definition: spxid.h:36
bool factorized
true iff factor = matrix .
Definition: spxbasis.h:357
void changedElement(int, int)
inform SPxBasis that a matrix entry had been changed.
rowwise representation.
Definition: spxsolver.h:107
Basis is singular.
Definition: spxbasis.h:93
Desc::Status dualRowStatus(int i) const
dual Status for the i&#39;th row variable of the loaded LP.
Definition: spxbasis.cpp:46
int nCols() const
returns number of columns.
Definition: spxbasis.h:219
void changedRow(int)
inform SPxBasis that a row had been changed.
Wrapper for different output streams and verbosity levels.
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:151
void removedCol(int i)
inform SPxBasis that column i had been removed.
primal variable is set to its upper bound
Definition: spxbasis.h:188
Generic Ids for LP rows or columns.Both SPxColIds and SPxRowIds may be treated uniformly as SPxIds: ...
Definition: spxid.h:85
SPxStatus status() const
returns current SPxStatus.
Definition: spxbasis.h:425
void reDim()
resizes internal arrays.
void setStatus(SPxStatus stat)
sets basis SPxStatus to stat.
Definition: spxbasis.h:431
void removedRows(const int perm[])
inform SPxBasis that rows in perm with negative entry were removed.
#define MSG_DEBUG(x)
Definition: spxdefines.h:129
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:111
main LP solver class
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1235
primal variable is left free, but unset
Definition: spxbasis.h:189
Status & colStatus(int i)
Definition: spxbasis.h:254
SPxId & baseId(int i)
Definition: spxbasis.h:503
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:119
void loadMatrixVecs()
loads matrix according to the SPxIds stored in theBaseId.
Definition: spxbasis.cpp:91
Debugging, floating point type and parameter definitions.
void restoreInitialBasis()
Restores initial basis.
Simplex basis.
Desc thedesc
the basis&#39; Descriptor
Definition: spxbasis.h:413
Everything should be within this namespace.
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:80
SPxOut * spxout
message handler
Definition: spxbasis.h:415
DataArray< SPxId > theBaseId
SPxIds of basic vectors.
Definition: spxbasis.h:345
primal variable is set to its lower bound
Definition: spxbasis.h:187
const VectorBase< R > & maxObj() const
Returns objective vector for maximization problem.
Definition: spxlpbase.h:429
SPxSolver * theLP
the LP
Definition: spxbasis.h:343
void removedRow(int i)
inform SPxBasis that row i had been removed.
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:157
Ids for LP rows.Class SPxRowId provides DataKeys for the row indices of an SPxLP. ...
Definition: spxid.h:55
const SVector & vector(int i) const
i &#39;th vector.
Definition: spxsolver.h:1129
int nRows() const
returns number of rows.
Definition: spxbasis.h:224
Status
Status of a variable.
Definition: spxbasis.h:185
LP has been proven to be primal unbounded.
Definition: spxbasis.h:98
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:483
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:469
columnwise representation.
Definition: spxsolver.h:108
Basis is primal feasible.
Definition: spxbasis.h:96
bool matrixIsSetup
true iff the pointers in matrix are set up correctly.
Definition: spxbasis.h:349
void addedCols(int n)
inform SPxBasis that n new columns had been added.
LP has been proven to be primal infeasible.
Definition: spxbasis.h:99
No Problem has been loaded to the basis.
Definition: spxbasis.h:92
DataArray< const SVector *> matrix
pointers to the vectors of the basis matrix.
Definition: spxbasis.h:347