Scippy

SoPlex

Sequential object-oriented simPlex

spxvecs.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 <assert.h>
17 #include <iostream>
18 
19 #include "spxdefines.h"
20 #include "spxsolver.h"
21 #include "exceptions.h"
22 
23 namespace soplex
24 {
25 /** Initialize Vectors
26 
27  Computing the right hand side vector for the feasibility vector depends on
28  the chosen representation and type of the basis.
29 
30  In columnwise case, |theFvec| = \f$x_B = A_B^{-1} (- A_N x_N)\f$, where \f$x_N\f$
31  are either upper or lower bounds for the nonbasic variables (depending on
32  the variables |Status|). If these values remain unchanged throughout the
33  simplex algorithm, they may be taken directly from LP. However, in the
34  entering type algorith they are changed and, hence, retreived from the
35  column or row upper or lower bound vectors.
36 
37  In rowwise case, |theFvec| = \f$\pi^T_B = (c^T - 0^T A_N) A_B^{-1}\f$. However,
38  this applies only to leaving type algorithm, where no bounds on dual
39  variables are altered. In entering type algorithm they are changed and,
40  hence, retreived from the column or row upper or lower bound vectors.
41  */
43 {
44 
45  if (rep() == COLUMN)
46  {
47  theFrhs->clear();
48 
49  if (type() == LEAVE)
50  {
52 
53  for(int i = 0; i < nRows(); i++)
54  {
55  Real x;
56 
58 
59  if (!isBasic(stat))
60  {
61  switch (stat)
62  {
63  // columnwise cases:
65  continue;
66 
68  assert(lhs(i) == rhs(i));
69  //lint -fallthrough
71  x = rhs(i);
72  break;
74  x = lhs(i);
75  break;
76 
77  default:
78  MSG_ERROR( std::cerr << "ESVECS01 ERROR: "
79  << "inconsistent basis must not happen!"
80  << std::endl; )
81  throw SPxInternalCodeException("XSVECS01 This should never happen.");
82  }
83  assert(x < infinity);
84  assert(x > -infinity);
85  (*theFrhs)[i] += x; // slack !
86  }
87  }
88  }
89  else
90  {
93  }
94  }
95  else
96  {
97  assert(rep() == ROW);
98 
99  if (type() == ENTER)
100  {
101  theFrhs->clear();
104  *theFrhs += maxObj();
105  }
106  else
107  {
108  ///@todo put this into a separate method
109  *theFrhs = maxObj();
110  const SPxBasis::Desc& ds = desc();
111  for (int i = 0; i < nRows(); ++i)
112  {
113  SPxBasis::Desc::Status stat = ds.rowStatus(i);
114 
115  if (!isBasic(stat))
116  {
117  Real x;
118 
119  switch (stat)
120  {
122  continue;
123 
127  x = maxRowObj(i);
128  break;
129 
130  default:
131  MSG_ERROR( std::cerr << "ESVECS04 ERROR: "
132  << "inconsistent basis must not happen!"
133  << std::endl; )
134  throw SPxInternalCodeException("XSVECS06 This should never happen.");
135  }
136  assert(x < infinity);
137  assert(x > -infinity);
138  // assert(x == 0.0);
139 
140  if (x != 0.0)
141  theFrhs->multAdd(x, vector(i));
142  }
143  }
144  }
145  }
146 }
147 
149 {
150 
151  assert(rep() == COLUMN);
152  assert(type() == LEAVE);
153 
154  for (int i = 0; i < nCols(); ++i)
155  {
157 
158  if (!isBasic(stat))
159  {
160  Real x;
161 
162  switch (stat)
163  {
164  // columnwise cases:
166  continue;
167 
169  assert(SPxLP::lower(i) == SPxLP::upper(i));
170  //lint -fallthrough
172  x = SPxLP::upper(i);
173  break;
175  x = SPxLP::lower(i);
176  break;
177 
178  default:
179  MSG_ERROR( std::cerr << "ESVECS02 ERROR: "
180  << "inconsistent basis must not happen!"
181  << std::endl; )
182  throw SPxInternalCodeException("XSVECS02 This should never happen.");
183  }
184  assert(x < infinity);
185  assert(x > -infinity);
186 
187  if (x != 0.0)
188  theFrhs->multAdd(-x, vector(i));
189  }
190  }
191 }
192 
193 
194 /** This methods subtracts \f$A_N x_N\f$ or \f$\pi_N^T A_N\f$ from |theFrhs| as
195  specified by the |Status| of all nonbasic variables. The values of \f$x_N\f$ or
196  \f$\pi_N\f$ are taken from the passed arrays.
197  */
199  const Vector& ufb, ///< upper feasibility bound for variables
200  const Vector& lfb) ///< lower feasibility bound for variables
201 {
202 
203  const SPxBasis::Desc& ds = desc();
204 
205  for (int i = 0; i < coDim(); ++i)
206  {
207  SPxBasis::Desc::Status stat = ds.status(i);
208 
209  if (!isBasic(stat))
210  {
211  Real x;
212 
213  switch (stat)
214  {
218  continue;
219 
222  x = ufb[i];
223  break;
226  x = lfb[i];
227  break;
228 
230  assert(lfb[i] == ufb[i]);
232  x = lfb[i];
233  break;
234 
235  default:
236  MSG_ERROR( std::cerr << "ESVECS03 ERROR: "
237  << "inconsistent basis must not happen!"
238  << std::endl; )
239  throw SPxInternalCodeException("XSVECS04 This should never happen.");
240  }
241  assert(x < infinity);
242  assert(x > -infinity);
243 
244  if (x != 0.0)
245  theFrhs->multAdd(-x, vector(i));
246  }
247  }
248 }
249 
250 /** This methods subtracts \f$A_N x_N\f$ or \f$\pi_N^T A_N\f$ from |theFrhs| as
251  specified by the |Status| of all nonbasic variables. The values of
252  \f$x_N\f$ or \f$\pi_N\f$ are taken from the passed arrays.
253  */
255  const Vector& coufb, ///< upper feasibility bound for covariables
256  const Vector& colfb) ///< lower feasibility bound for covariables
257 {
258  const SPxBasis::Desc& ds = desc();
259 
260  for(int i = 0; i < dim(); ++i)
261  {
262  SPxBasis::Desc::Status stat = ds.coStatus(i);
263 
264  if (!isBasic(stat))
265  {
266  Real x;
267 
268  switch (stat)
269  {
273  continue;
274 
275  case SPxBasis::Desc::P_ON_LOWER : // negative slack bounds!
277  x = coufb[i];
278  break;
279  case SPxBasis::Desc::P_ON_UPPER : // negative slack bounds!
281  x = colfb[i];
282  break;
285 
286  if (colfb[i] != coufb[i])
287  {
288  MSG_WARNING( (*spxout), (*spxout) << "WSVECS04 Frhs2[" << i << "]: " << stat << " "
289  << colfb[i] << " " << coufb[i]
290  << " shouldn't be" << std::endl; )
291  }
292  assert(colfb[i] == coufb[i]);
293  x = colfb[i];
294  break;
295 
296  default:
297  MSG_ERROR( std::cerr << "ESVECS05 ERROR: "
298  << "inconsistent basis must not happen!"
299  << std::endl; )
300  throw SPxInternalCodeException("XSVECS05 This should never happen.");
301  }
302  assert(x < infinity);
303  assert(x > -infinity);
304 
305  (*theFrhs)[i] -= x; // This is a slack, so no need to multiply a vector.
306  }
307  }
308 }
309 
310 /** Computing the right hand side vector for |theCoPvec| depends on
311  the type of the simplex algorithm. In entering algorithms, the
312  values are taken from the inequality's right handside or the
313  column's objective value.
314 
315  In contrast to this leaving algorithms take the values from vectors
316  |theURbound| and so on.
317 
318  We reflect this difference by providing two pairs of methods
319  |computeEnterCoPrhs(n, stat)| and |computeLeaveCoPrhs(n, stat)|. The first
320  pair operates for entering algorithms, while the second one is intended for
321  leaving algorithms. The return value of these methods is the right hand
322  side value for the \f$n\f$-th row or column id, respectively, if it had the
323  passed |Status| for both.
324 
325  Both methods are again split up into two methods named |...4Row(i,n)| and
326  |...4Col(i,n)|, respectively. They do their job for the |i|-th basis
327  variable, being the |n|-th row or column.
328 */
330 {
331  assert(baseId(i).isSPxRowId());
332  assert(number(SPxRowId(baseId(i))) == n);
333 
334  switch (desc().rowStatus(n))
335  {
336  // rowwise representation:
338  assert(lhs(n) > -infinity);
339  assert(rhs(n) == lhs(n));
340  //lint -fallthrough
342  assert(rep() == ROW);
343  assert(rhs(n) < infinity);
344  (*theCoPrhs)[i] = rhs(n);
345  break;
347  assert(rep() == ROW);
348  assert(lhs(n) > -infinity);
349  (*theCoPrhs)[i] = lhs(n);
350  break;
351 
352  // columnwise representation:
353  // slacks must be left 0!
354  default:
355  (*theCoPrhs)[i] = maxRowObj(n);
356  break;
357  }
358 }
359 
361 {
362  assert(baseId(i).isSPxColId());
363  assert(number(SPxColId(baseId(i))) == n);
364  switch (desc().colStatus(n))
365  {
366  // rowwise representation:
368  assert(SPxLP::upper(n) == SPxLP::lower(n));
369  assert(SPxLP::lower(n) > -infinity);
370  //lint -fallthrough
372  assert(rep() == ROW);
373  assert(SPxLP::upper(n) < infinity);
374  (*theCoPrhs)[i] = SPxLP::upper(n);
375  break;
377  assert(rep() == ROW);
378  assert(SPxLP::lower(n) > -infinity);
379  (*theCoPrhs)[i] = SPxLP::lower(n);
380  break;
381 
382  // columnwise representation:
388  assert(rep() == COLUMN);
389  (*theCoPrhs)[i] = maxObj(n);
390  break;
391 
392  default: // variable left 0
393  (*theCoPrhs)[i] = 0;
394  break;
395  }
396 }
397 
399 {
400  assert(type() == ENTER);
401 
402  for (int i = dim() - 1; i >= 0; --i)
403  {
404  SPxId l_id = baseId(i);
405  if (l_id.isSPxRowId())
407  else
409  }
410 }
411 
413 {
414  assert(baseId(i).isSPxRowId());
415  assert(number(SPxRowId(baseId(i))) == n);
416  switch (desc().rowStatus(n))
417  {
420  assert(theLRbound[n] > -infinity);
421  assert(theURbound[n] == theLRbound[n]);
422  //lint -fallthrough
425  assert(theURbound[n] < infinity);
426  (*theCoPrhs)[i] = theURbound[n];
427  break;
428 
431  assert(theLRbound[n] > -infinity);
432  (*theCoPrhs)[i] = theLRbound[n];
433  break;
434 
435  default:
436  (*theCoPrhs)[i] = maxRowObj(n);
437  break;
438  }
439 }
440 
442 {
443  assert(baseId(i).isSPxColId());
444  assert(number(SPxColId(baseId(i))) == n);
445  switch (desc().colStatus(n))
446  {
450  assert(theLCbound[n] > -infinity);
451  assert(theUCbound[n] == theLCbound[n]);
452  //lint -fallthrough
455  assert(theUCbound[n] < infinity);
456  (*theCoPrhs)[i] = theUCbound[n];
457  break;
460  assert(theLCbound[n] > -infinity);
461  (*theCoPrhs)[i] = theLCbound[n];
462  break;
463 
464  default:
465  (*theCoPrhs)[i] = maxObj(n);
466  // (*theCoPrhs)[i] = 0;
467  break;
468  }
469 }
470 
472 {
473  assert(type() == LEAVE);
474 
475  for (int i = dim() - 1; i >= 0; --i)
476  {
477  SPxId l_id = baseId(i);
478  if (l_id.isSPxRowId())
480  else
482  }
483 }
484 
485 
486 /** When computing the copricing vector, we expect the pricing vector to be
487  setup correctly. Then computing the copricing vector is nothing but
488  computing all scalar products of the pricing vector with the vectors of the
489  LPs constraint matrix.
490  */
492 {
493  int i;
494 
495  for (i = coDim() - 1; i >= 0; --i)
496  (*thePvec)[i] = vector(i) * (*theCoPvec);
497 }
498 
500 {
501  SSVector& p = thePvec->delta();
502  SSVector& c = theCoPvec->delta();
503 
504  if (c.isSetup())
505  {
506  if (c.size() < 0.95 * theCoPvec->dim())
508  else
509  p.assign2product(c, *thevectors);
510  }
511  else
512  {
514  }
515 
516  p.setup();
517 }
518 
520 {
521  theCoPvec->update();
522  if (pricing() == FULL)
523  {
524  // thePvec->delta().setup();
525  thePvec->update();
526  }
527 }
528 } // namespace soplex