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->has(SPxRowId(id)))
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() && !theLP->has(SPxColId(id)))
336  {
337  baseId(j) = baseId(theLP->dim());
338  if ( matrixIsSetup &&
339  j < theLP->dim() )
340  matrix[j] = &theLP->vector(baseId(j));
341  break;
342  }
343  }
344  }
345  }
346 
348  reDim();
349 }
350 
351 void SPxBasis::removedCols(const int perm[])
352 {
353  assert(status() > NO_PROBLEM);
354  assert(theLP != 0);
355 
356  int i;
357  int n = thedesc.nCols();
358 
359  if (theLP->rep() == SPxSolver::COLUMN)
360  {
361  for (i = 0; i < n; ++i)
362  {
363  if (perm[i] < 0) // column got removed
364  {
365  if (theLP->isBasic(thedesc.colStatus(i)))
367  }
368  else // column was potentially moved
369  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
370  }
371  }
372  else
373  {
374  assert(theLP->rep() == SPxSolver::ROW);
375  factorized = matrixIsSetup = false;
376  for (i = 0; i < n; ++i)
377  {
378  if (perm[i] != i)
379  {
380  if (perm[i] < 0) // column got removed
381  {
382  if (!theLP->isBasic(thedesc.colStatus(i)))
384  }
385  else // column was moved
386  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
387  }
388  }
389  }
390 
391  reDim();
392 }
393 
394 
395 /**
396  * mark the basis as not factorized
397  */
399 {
400  if( factorized || matrixIsSetup )
401  {
402  MSG_INFO3( (*spxout), (*spxout) << "ICHBAS09 explicit invalidation of factorization" << std::endl; )
403  }
404 
405  factorized = false;
406  matrixIsSetup = false;
407 }
408 
409 
410 /**
411  * Create the initial slack basis descriptor and set up the basis matrix accordingly.
412  * This code has been adapted from SPxBasis::addedRows() and SPxBasis::addedCols().
413  */
415 {
416  assert(!factorized);
417 
418  MSG_INFO3( (*spxout), (*spxout) << "ICHBAS10 setup slack basis" << std::endl; )
419 
420  if (theLP->rep() == SPxSolver::COLUMN)
421  {
422  for (int i = 0; i < theLP->nRows(); ++i)
423  {
425  baseId(i) = theLP->SPxLP::rId(i);
426  }
427 
428  for (int i = 0; i < theLP->nCols(); ++i)
430  }
431  else
432  {
433  assert(theLP->rep() == SPxSolver::ROW);
434 
435  for (int i = 0; i < theLP->nRows(); ++i)
437 
438  for (int i = 0; i < theLP->nCols(); ++i)
439  {
441  baseId(i) = theLP->SPxLP::cId(i);
442  }
443  }
444 
445  /* if matrix was set up, load new basis vectors to the matrix */
446  if (status() > NO_PROBLEM && matrixIsSetup)
447  loadMatrixVecs();
448 
449  /* update basis status */
451 }
452 
453 /**
454  * @todo Implement changedRow(), changedCol(), changedElement() in a more clever
455  * way. For instance, the basis won't be singular (but maybe infeasible) if the
456  * change doesn't affect the basis rows/columns.
457  *
458  * The following methods (changedRow(), changedCol(), changedElement()) radically
459  * change the current basis to the original (slack) basis also present after
460  * loading the LP. The reason is that through the changes, the current basis may
461  * become singular. Going back to the initial basis is quite inefficient, but
462  * correct.
463  */
464 
465 /**@todo is this correctly implemented?
466  */
467 void SPxBasis::changedRow(int /*row*/)
468 {
469  invalidate();
471 }
472 
473 /**@todo is this correctly implemented?
474  */
475 void SPxBasis::changedCol(int /*col*/)
476 {
477  invalidate();
479 }
480 
481 /**@todo is this correctly implemented?
482  */
483 void SPxBasis::changedElement(int /*row*/, int /*col*/)
484 {
485  invalidate();
487 }
488 } // 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.
bool has(const SPxRowId &id) const
Returns the row number of the row with identifier id.
Definition: spxlpbase.h:542
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.
static SPxBasis::Desc::Status primalColStatus(int i, const SPxLP *theLP)
int dim() const
dimension of basis matrix.
Definition: spxsolver.h:1056
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:132
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:114
main LP solver class
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1244
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:122
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:1138
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:478
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