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-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 #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 
59 {
60 
61  assert(theLP != 0);
62 
63  if( n > 0 )
64  {
65  reDim();
66 
67  if (theLP->rep() == SPxSolver::COLUMN)
68  {
69  /* I think, after adding rows in column representation,
70  reDim should set these bools to false. */
71  assert( !matrixIsSetup && !factorized );
72 
73  for (int i = theLP->nRows() - n; i < theLP->nRows(); ++i)
74  {
76  baseId(i) = theLP->SPxLP::rId(i);
77  }
78 
79  /* ??? I think, this cannot happen. */
80  /* if matrix was set up, load new basis vectors to the matrix */
81  if (status() > NO_PROBLEM && matrixIsSetup)
83  }
84  else
85  {
86  assert(theLP->rep() == SPxSolver::ROW);
87 
88  for (int i = theLP->nRows() - n; i < theLP->nRows(); ++i)
90 
91  /* In the row case, the basis is not effected by adding rows. However,
92  * since @c matrix stores references to the rows in the LP (SPxLP), a realloc
93  * in SPxLP (e.g. due to space requirements) might invalidate these references.
94  * We therefore have to "reload" the matrix if it is set up. Note that reDim()
95  * leaves @c matrixIsSetup untouched if only row have been added, since the basis
96  * matrix already has the correct size. */
97  if (status() > NO_PROBLEM && matrixIsSetup)
99  }
100 
101  /* update basis status */
102  switch (status())
103  {
104  case PRIMAL:
105  case UNBOUNDED:
107  break;
108  case OPTIMAL:
109  case INFEASIBLE:
110  setStatus(DUAL);
111  break;
112  case NO_PROBLEM:
113  case SINGULAR:
114  case REGULAR:
115  case DUAL:
116  break;
117  default:
118  MSG_ERROR( std::cerr << "ECHBAS04 Unknown basis status!" << std::endl; )
119  throw SPxInternalCodeException("XCHBAS01 This should never happen.");
120  }
121  }
122 }
123 
125 {
126 
127  assert(status() > NO_PROBLEM);
128  assert(theLP != 0);
129 
130  if (theLP->rep() == SPxSolver::ROW)
131  {
132  if (theLP->isBasic(thedesc.rowStatus(i)))
133  {
135  factorized = false;
136 
137  MSG_DEBUG( std::cout << "DCHBAS05 Warning: deleting basic row!\n"; )
138  }
139  }
140  else
141  {
142  assert(theLP->rep() == SPxSolver::COLUMN);
143  factorized = false;
144  if (!theLP->isBasic(thedesc.rowStatus(i)))
145  {
147  MSG_DEBUG( std::cout << "DCHBAS06 Warning: deleting nonbasic row!\n"; )
148  }
149  else if (status() > NO_PROBLEM && matrixIsSetup)
150  {
151  for (int j = theLP->dim(); j >= 0; --j)
152  {
153  SPxId id = baseId(j);
154 
155  if (id.isSPxRowId() && theLP->number(SPxRowId(id)) < 0)
156  {
157  baseId(j) = baseId(theLP->dim());
158 
159  if (j < theLP->dim())
160  matrix[j] = &theLP->vector(baseId(j));
161  break;
162  }
163  }
164  }
165  }
167  reDim();
168 }
169 
170 void SPxBasis::removedRows(const int perm[])
171 {
172  assert(status() > NO_PROBLEM);
173  assert(theLP != 0);
174 
175  int i;
176  int n = thedesc.nRows();
177 
178  if (theLP->rep() == SPxSolver::ROW)
179  {
180  for (i = 0; i < n; ++i)
181  {
182  if (perm[i] != i)
183  {
184  if (perm[i] < 0) // row got removed
185  {
186  if (theLP->isBasic(thedesc.rowStatus(i)))
187  {
189  factorized = matrixIsSetup = false;
190  MSG_DEBUG( std::cout << "DCHBAS07 Warning: deleting basic row!\n"; )
191  }
192  }
193  else // row was moved
194  thedesc.rowStatus(perm[i]) = thedesc.rowStatus(i);
195  }
196  }
197  }
198  else
199  {
200  assert(theLP->rep() == SPxSolver::COLUMN);
201 
202  factorized = false;
203  matrixIsSetup = false;
204 
205  for (i = 0; i < n; ++i)
206  {
207  if (perm[i] != i)
208  {
209  if (perm[i] < 0) // row got removed
210  {
211  if (!theLP->isBasic(thedesc.rowStatus(i)))
213  }
214  else // row was moved
215  thedesc.rowStatus(perm[i]) = thedesc.rowStatus(i);
216  }
217  }
218  }
219  reDim();
220 }
221 
222 
225 {
226  assert(theLP != 0);
227 
228  if (theLP->upper(i) < infinity)
229  {
230  if (theLP->lower(i) > -infinity)
231  {
232  if (theLP->lower(i) == theLP->SPxLP::upper(i))
234  /*
235  else
236  return (-theLP->lower(i) < theLP->upper(i))
237  ? SPxBasis::Desc::P_ON_LOWER
238  : SPxBasis::Desc::P_ON_UPPER;
239  */
240  else if (theLP->maxObj(i) == 0)
241  return (-theLP->lower(i) < theLP->upper(i))
244  else
245  return (theLP->maxObj(i) < 0)
248  }
249  else
251  }
252  else if (theLP->lower(i) > -infinity)
254  else
255  return SPxBasis::Desc::P_FREE;
256 }
257 
258 
260 {
261  assert(theLP != 0);
262 
263  if( n > 0 )
264  {
265  reDim();
266 
267  if (theLP->rep() == SPxSolver::ROW)
268  {
269  /* I think, after adding columns in row representation,
270  reDim should set these bools to false. */
271  assert( !matrixIsSetup && !factorized );
272 
273  for (int i = theLP->nCols() - n; i < theLP->nCols(); ++i)
274  {
276  baseId(i) = theLP->SPxLP::cId(i);
277  }
278 
279  /* ??? I think, this cannot happen. */
280  /* if matrix was set up, load new basis vectors to the matrix */
281  if (status() > NO_PROBLEM && matrixIsSetup)
282  loadMatrixVecs();
283  }
284  else
285  {
286  assert(theLP->rep() == SPxSolver::COLUMN);
287 
288  for (int i = theLP->nCols() - n; i < theLP->nCols(); ++i)
290 
291  /* In the column case, the basis is not effected by adding columns. However,
292  * since @c matrix stores references to the columns in the LP (SPxLP), a realloc
293  * in SPxLP (e.g. due to space requirements) might invalidate these references.
294  * We therefore have to "reload" the matrix if it is set up. Note that reDim()
295  * leaves @c matrixIsSetup untouched if only columns have been added, since the
296  * basis matrix already has the correct size. */
297  if (status() > NO_PROBLEM && matrixIsSetup)
298  loadMatrixVecs();
299  }
300 
301  switch (status())
302  {
303  case DUAL:
304  case INFEASIBLE:
306  break;
307  case OPTIMAL:
308  case UNBOUNDED:
309  setStatus(PRIMAL);
310  break;
311  case NO_PROBLEM:
312  case SINGULAR:
313  case REGULAR:
314  case PRIMAL:
315  break;
316  default:
317  MSG_ERROR( std::cerr << "ECHBAS08 Unknown basis status!" << std::endl; )
318  throw SPxInternalCodeException("XCHBAS02 This should never happen.");
319  }
320  }
321 }
322 
324 {
325  assert(status() > NO_PROBLEM);
326  assert(theLP != 0);
327 
328  if (theLP->rep() == SPxSolver::COLUMN)
329  {
330  if (theLP->isBasic(thedesc.colStatus(i)))
332  }
333  else
334  {
335  assert(theLP->rep() == SPxSolver::ROW);
336  factorized = false;
337  if (!theLP->isBasic(thedesc.colStatus(i)))
339  else if (status() > NO_PROBLEM)
340  {
341  for (int j = theLP->dim(); j >= 0; --j)
342  {
343  SPxId id = baseId(j);
344  if (id.isSPxColId()
345  && theLP->number(SPxColId(id)) < 0)
346  {
347  baseId(j) = baseId(theLP->dim());
348  if ( matrixIsSetup &&
349  j < theLP->dim() )
350  matrix[j] = &theLP->vector(baseId(j));
351  break;
352  }
353  }
354  }
355  }
356 
358  reDim();
359 }
360 
361 void SPxBasis::removedCols(const int perm[])
362 {
363  assert(status() > NO_PROBLEM);
364  assert(theLP != 0);
365 
366  int i;
367  int n = thedesc.nCols();
368 
369  if (theLP->rep() == SPxSolver::COLUMN)
370  {
371  for (i = 0; i < n; ++i)
372  {
373  if (perm[i] < 0) // column got removed
374  {
375  if (theLP->isBasic(thedesc.colStatus(i)))
377  }
378  else // column was potentially moved
379  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
380  }
381  }
382  else
383  {
384  assert(theLP->rep() == SPxSolver::ROW);
385  factorized = matrixIsSetup = false;
386  for (i = 0; i < n; ++i)
387  {
388  if (perm[i] != i)
389  {
390  if (perm[i] < 0) // column got removed
391  {
392  if (!theLP->isBasic(thedesc.colStatus(i)))
394  }
395  else // column was moved
396  thedesc.colStatus(perm[i]) = thedesc.colStatus(i);
397  }
398  }
399  }
400 
401  reDim();
402 }
403 
404 
405 /**@todo is this correctly implemented?
406  */
408 {
409  assert(spxout != 0);
410  if( spxout != 0 )
411  {
412  MSG_INFO3( (*spxout), (*spxout) << "ICHBAS09 explicit invalidation of factorization" << std::endl; )
413  }
414 
415  factorized = false;
416  matrixIsSetup = false;
417 }
418 
419 
420 /**
421  This code has been adapted from SPxBasis::addedRows() and
422  SPxBasis::addedCols().
423 */
425 {
426 
427  assert( !matrixIsSetup && !factorized );
428 
429  if (theLP->rep() == SPxSolver::COLUMN)
430  {
431  for (int i = 0; i < theLP->nRows(); ++i)
432  {
434  baseId(i) = theLP->SPxLP::rId(i);
435  }
436 
437  for (int i = 0; i < theLP->nCols(); ++i)
439 
440  /* ??? I think, this cannot happen. */
441  /* if matrix was set up, load new basis vectors to the matrix */
442  if (status() > NO_PROBLEM && matrixIsSetup)
443  loadMatrixVecs();
444  }
445  else
446  {
447  assert(theLP->rep() == SPxSolver::ROW);
448 
449  for (int i = 0; i < theLP->nRows(); ++i)
451 
452  for (int i = 0; i < theLP->nCols(); ++i)
453  {
455  baseId(i) = theLP->SPxLP::cId(i);
456  }
457 
458  /* ??? I think, this cannot happen. */
459  /* if matrix was set up, load new basis vectors to the matrix */
460  if (status() > NO_PROBLEM && matrixIsSetup)
461  loadMatrixVecs();
462  }
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