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-2019 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 "soplex/spxdefines.h"
19 #include "soplex/spxbasis.h"
20 #include "soplex/spxsolver.h"
21 #include "soplex/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. */
95 
96  /* update basis status */
97  switch(status())
98  {
99  case PRIMAL:
100  case UNBOUNDED:
102  break;
103 
104  case OPTIMAL:
105  case INFEASIBLE:
106  setStatus(DUAL);
107  break;
108 
109  case NO_PROBLEM:
110  case SINGULAR:
111  case REGULAR:
112  case DUAL:
113  break;
114 
115  default:
116  MSG_ERROR(std::cerr << "ECHBAS04 Unknown basis status!" << std::endl;)
117  throw SPxInternalCodeException("XCHBAS01 This should never happen.");
118  }
119  }
120 }
121 
123 {
124 
125  assert(status() > NO_PROBLEM);
126  assert(theLP != 0);
127 
128  if(theLP->rep() == SPxSolver::ROW)
129  {
130  if(theLP->isBasic(thedesc.rowStatus(i)))
131  {
133  factorized = false;
134 
135  MSG_DEBUG(std::cout << "DCHBAS05 Warning: deleting basic row!\n";)
136  }
137  }
138  else
139  {
140  assert(theLP->rep() == SPxSolver::COLUMN);
141  factorized = false;
142 
143  if(!theLP->isBasic(thedesc.rowStatus(i)))
144  {
146  MSG_DEBUG(std::cout << "DCHBAS06 Warning: deleting nonbasic row!\n";)
147  }
148  else if(status() > NO_PROBLEM && matrixIsSetup)
149  {
150  for(int j = theLP->dim(); j >= 0; --j)
151  {
152  SPxId id = baseId(j);
153 
154  if(id.isSPxRowId() && !theLP->has(SPxRowId(id)))
155  {
156  baseId(j) = baseId(theLP->dim());
157 
158  if(j < theLP->dim())
159  matrix[j] = &theLP->vector(baseId(j));
160 
161  break;
162  }
163  }
164  }
165  }
166 
168  reDim();
169 }
170 
171 void SPxBasis::removedRows(const int perm[])
172 {
173  assert(status() > NO_PROBLEM);
174  assert(theLP != 0);
175 
176  int i;
177  int n = thedesc.nRows();
178 
179  if(theLP->rep() == SPxSolver::ROW)
180  {
181  for(i = 0; i < n; ++i)
182  {
183  if(perm[i] != i)
184  {
185  if(perm[i] < 0) // row got removed
186  {
187  if(theLP->isBasic(thedesc.rowStatus(i)))
188  {
190  factorized = matrixIsSetup = false;
191  MSG_DEBUG(std::cout << "DCHBAS07 Warning: deleting basic row!\n";)
192  }
193  }
194  else // row was moved
195  thedesc.rowStatus(perm[i]) = thedesc.rowStatus(i);
196  }
197  }
198  }
199  else
200  {
201  assert(theLP->rep() == SPxSolver::COLUMN);
202 
203  factorized = false;
204  matrixIsSetup = false;
205 
206  for(i = 0; i < n; ++i)
207  {
208  if(perm[i] != i)
209  {
210  if(perm[i] < 0) // row got removed
211  {
212  if(!theLP->isBasic(thedesc.rowStatus(i)))
214  }
215  else // row was moved
216  thedesc.rowStatus(perm[i]) = thedesc.rowStatus(i);
217  }
218  }
219  }
220 
221  reDim();
222 }
223 
224 
227 {
228  assert(theLP != 0);
229 
230  if(theLP->upper(i) < infinity)
231  {
232  if(theLP->lower(i) > -infinity)
233  {
234  if(theLP->lower(i) == theLP->SPxLP::upper(i))
236  /*
237  else
238  return (-theLP->lower(i) < theLP->upper(i))
239  ? SPxBasis::Desc::P_ON_LOWER
240  : SPxBasis::Desc::P_ON_UPPER;
241  */
242  else if(theLP->maxObj(i) == 0)
243  return (-theLP->lower(i) < theLP->upper(i))
246  else
247  return (theLP->maxObj(i) < 0)
250  }
251  else
253  }
254  else if(theLP->lower(i) > -infinity)
256  else
257  return SPxBasis::Desc::P_FREE;
258 }
259 
260 
261 /* adapt basis and basis descriptor to added columns */
263 {
264  assert(theLP != 0);
265 
266  if(n > 0)
267  {
268  reDim();
269 
270  if(theLP->rep() == SPxSolver::ROW)
271  {
272  /* after adding columns in row representation, reDim() should set these bools to false. */
273  assert(!matrixIsSetup && !factorized);
274 
275  for(int i = theLP->nCols() - n; i < theLP->nCols(); ++i)
276  {
278  baseId(i) = theLP->SPxLP::cId(i);
279  }
280  }
281  else
282  {
283  assert(theLP->rep() == SPxSolver::COLUMN);
284 
285  for(int i = theLP->nCols() - n; i < theLP->nCols(); ++i)
287  }
288 
289  /* If matrix was set up, load new basis vectors to the matrix
290  * In the column case, the basis is not effected by adding columns. However,
291  * since @c matrix stores references to the columns in the LP (SPxLP), a realloc
292  * in SPxLP (e.g. due to space requirements) might invalidate these references.
293  * We therefore have to "reload" the matrix if it is set up. Note that reDim()
294  * leaves @c matrixIsSetup untouched if only columns have been added, since the
295  * basis matrix already has the correct size. */
296  if(status() > NO_PROBLEM && matrixIsSetup)
297  loadMatrixVecs();
298 
299  switch(status())
300  {
301  case DUAL:
302  case INFEASIBLE:
304  break;
305 
306  case OPTIMAL:
307  case UNBOUNDED:
308  setStatus(PRIMAL);
309  break;
310 
311  case NO_PROBLEM:
312  case SINGULAR:
313  case REGULAR:
314  case PRIMAL:
315  break;
316 
317  default:
318  MSG_ERROR(std::cerr << "ECHBAS08 Unknown basis status!" << std::endl;)
319  throw SPxInternalCodeException("XCHBAS02 This should never happen.");
320  }
321  }
322 }
323 
325 {
326  assert(status() > NO_PROBLEM);
327  assert(theLP != 0);
328 
329  if(theLP->rep() == SPxSolver::COLUMN)
330  {
331  if(theLP->isBasic(thedesc.colStatus(i)))
333  }
334  else
335  {
336  assert(theLP->rep() == SPxSolver::ROW);
337  factorized = false;
338 
339  if(!theLP->isBasic(thedesc.colStatus(i)))
341  else if(status() > NO_PROBLEM)
342  {
343  for(int j = theLP->dim(); j >= 0; --j)
344  {
345  SPxId id = baseId(j);
346 
347  if(id.isSPxColId() && !theLP->has(SPxColId(id)))
348  {
349  baseId(j) = baseId(theLP->dim());
350 
351  if(matrixIsSetup &&
352  j < theLP->dim())
353  matrix[j] = &theLP->vector(baseId(j));
354 
355  break;
356  }
357  }
358  }
359  }
360 
362  reDim();
363 }
364 
365 void SPxBasis::removedCols(const int perm[])
366 {
367  assert(status() > NO_PROBLEM);
368  assert(theLP != 0);
369 
370  int i;
371  int n = thedesc.nCols();
372 
373  if(theLP->rep() == SPxSolver::COLUMN)
374  {
375  for(i = 0; i < n; ++i)
376  {
377  if(perm[i] < 0) // column got removed
378  {
379  if(theLP->isBasic(thedesc.colStatus(i)))
381  }
382  else // column was potentially moved
383  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
384  }
385  }
386  else
387  {
388  assert(theLP->rep() == SPxSolver::ROW);
389  factorized = matrixIsSetup = false;
390 
391  for(i = 0; i < n; ++i)
392  {
393  if(perm[i] != i)
394  {
395  if(perm[i] < 0) // column got removed
396  {
397  if(!theLP->isBasic(thedesc.colStatus(i)))
399  }
400  else // column was moved
401  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
402  }
403  }
404  }
405 
406  reDim();
407 }
408 
409 
410 /**
411  * mark the basis as not factorized
412  */
414 {
416  {
417  MSG_INFO3((*spxout), (*spxout) << "ICHBAS09 explicit invalidation of factorization" << std::endl;)
418  }
419 
420  factorized = false;
421  matrixIsSetup = false;
422 }
423 
424 
425 /**
426  * Create the initial slack basis descriptor and set up the basis matrix accordingly.
427  * This code has been adapted from SPxBasis::addedRows() and SPxBasis::addedCols().
428  */
430 {
431  assert(!factorized);
432 
433  MSG_INFO3((*spxout), (*spxout) << "ICHBAS10 setup slack basis" << std::endl;)
434 
435  if(theLP->rep() == SPxSolver::COLUMN)
436  {
437  for(int i = 0; i < theLP->nRows(); ++i)
438  {
440  baseId(i) = theLP->SPxLP::rId(i);
441  }
442 
443  for(int i = 0; i < theLP->nCols(); ++i)
445  }
446  else
447  {
448  assert(theLP->rep() == SPxSolver::ROW);
449 
450  for(int i = 0; i < theLP->nRows(); ++i)
452 
453  for(int i = 0; i < theLP->nCols(); ++i)
454  {
456  baseId(i) = theLP->SPxLP::cId(i);
457  }
458  }
459 
460  /* if matrix was set up, load new basis vectors to the matrix */
461  if(status() > NO_PROBLEM && matrixIsSetup)
462  loadMatrixVecs();
463 
464  /* update basis status */
466 }
467 
468 /**
469  * @todo Implement changedRow(), changedCol(), changedElement() in a more clever
470  * way. For instance, the basis won't be singular (but maybe infeasible) if the
471  * change doesn't affect the basis rows/columns.
472  *
473  * The following methods (changedRow(), changedCol(), changedElement()) radically
474  * change the current basis to the original (slack) basis also present after
475  * loading the LP. The reason is that through the changes, the current basis may
476  * become singular. Going back to the initial basis is quite inefficient, but
477  * correct.
478  */
479 
480 /**@todo is this correctly implemented?
481  */
482 void SPxBasis::changedRow(int /*row*/)
483 {
484  invalidate();
486 }
487 
488 /**@todo is this correctly implemented?
489  */
490 void SPxBasis::changedCol(int /*col*/)
491 {
492  invalidate();
494 }
495 
496 /**@todo is this correctly implemented?
497  */
498 void SPxBasis::changedElement(int /*row*/, int /*col*/)
499 {
500  invalidate();
502 }
503 } // 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:461
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:547
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:1075
void reSize(int rowDim, int colDim)
resets dimensions.
Definition: spxdesc.cpp:95
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:152
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:1263
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:504
#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:434
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:158
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:1157
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:488
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:506
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