Scippy

SoPlex

Sequential object-oriented simPlex

spxdefaultrt.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 <assert.h>
17 #include <iostream>
18 
19 #include "spxdefines.h"
20 #include "spxdefaultrt.h"
21 
22 namespace soplex
23 {
24 /**
25  * Here comes the ratio test for selecting a variable to leave the basis.
26  * It is assumed that Vec.delta() and fVec.idx() have been setup
27  * correctly!
28  *
29  * The leaving variable is selected such that the update of fVec() (using
30  * fVec.value() * fVec.delta()) keeps the basis feasible within
31  * solver()->entertol(). Hence, fVec.value() must be chosen such that one
32  * updated value of theFvec just reaches its bound and no other one exceeds
33  * them by more than solver()->entertol(). Further, fVec.value() must have the
34  * same sign as argument \p val.
35  *
36  * The return value of selectLeave() is the number of a variable in the
37  * basis selected to leave the basis. -1 indicates that no variable could be
38  * selected. Otherwise, parameter \p val contains the chosen fVec.value().
39  */
41 {
42  solver()->fVec().delta().setup();
43 
44  const Real* vec = solver()->fVec().get_const_ptr();
45  const Real* upd = solver()->fVec().delta().values();
46  const IdxSet& idx = solver()->fVec().idx();
47  const Real* ub = solver()->ubBound().get_const_ptr();
48  const Real* lb = solver()->lbBound().get_const_ptr();
49 
50  Real epsilon = solver()->epsilon();
51  int leave = -1;
52 
53  Real x;
54  int i;
55  int j;
56 
57  // PARALLEL the j loop could be parallelized
58  if (val > 0)
59  {
60  // Loop over NZEs of delta vector.
61  for( j = 0; j < idx.size(); ++j)
62  {
63  i = idx.index(j);
64  x = upd[i];
65 
66  if (x > epsilon)
67  {
68  if (ub[i] < infinity)
69  {
70  Real y = (ub[i] - vec[i] + delta) / x;
71 
72  if (y < val)
73  {
74  leave = i;
75  val = y;
76  }
77  }
78  }
79  else if (x < -epsilon)
80  {
81  if (lb[i] > -infinity)
82  {
83  Real y = (lb[i] - vec[i] - delta) / x;
84 
85  if (y < val)
86  {
87  leave = i;
88  val = y;
89  }
90  }
91  }
92  }
93  if (leave >= 0)
94  {
95  x = upd[leave];
96 
97  // BH 2005-11-30: It may well happen that the basis is degenerate and the
98  // selected leaving variable is (at most delta) beyond its bound. (This
99  // happens for instance on LP/netlib/adlittle.mps with setting -r -t0.)
100  // In that case we do a pivot step with length zero to avoid difficulties.
101  if ( ( x > epsilon && vec[leave] >= ub[leave] ) ||
102  ( x < -epsilon && vec[leave] <= lb[leave] ) )
103  {
104  val = 0.0;
105  }
106  else
107  {
108  val = (x > epsilon) ? ub[leave] : lb[leave];
109  val = (val - vec[leave]) / x;
110  }
111  }
112 
113  ASSERT_WARN( "WDEFRT01", val > -epsilon );
114  }
115  else
116  {
117  for( j = 0; j < idx.size(); ++j)
118  {
119  i = idx.index(j);
120  x = upd[i];
121 
122  if (x < -epsilon)
123  {
124  if (ub[i] < infinity)
125  {
126  Real y = (ub[i] - vec[i] + delta) / x;
127 
128  if (y > val)
129  {
130  leave = i;
131  val = y;
132  }
133  }
134  }
135  else if (x > epsilon)
136  {
137  if (lb[i] > -infinity)
138  {
139  Real y = (lb[i] - vec[i] - delta) / x;
140 
141  if (y > val)
142  {
143  leave = i;
144  val = y;
145  }
146  }
147  }
148  }
149  if (leave >= 0)
150  {
151  x = upd[leave];
152 
153  // See comment above.
154  if ( ( x < -epsilon && vec[leave] >= ub[leave] ) ||
155  ( x > epsilon && vec[leave] <= lb[leave] ) )
156  {
157  val = 0.0;
158  }
159  else
160  {
161  val = (x < epsilon) ? ub[leave] : lb[leave];
162  val = (val - vec[leave]) / x;
163  }
164  }
165 
166  ASSERT_WARN( "WDEFRT02", val < epsilon );
167  }
168  return leave;
169 }
170 
171 /**
172  Here comes the ratio test. It is assumed that theCoPvec.delta() and
173  theCoPvec.idx() have been setup correctly!
174  */
176 {
177  solver()->coPvec().delta().setup();
178  solver()->pVec().delta().setup();
179 
180  const Real* pvec = solver()->pVec().get_const_ptr();
181  const Real* pupd = solver()->pVec().delta().values();
182  const IdxSet& pidx = solver()->pVec().idx();
183  const Real* lpb = solver()->lpBound().get_const_ptr();
184  const Real* upb = solver()->upBound().get_const_ptr();
185 
186  const Real* cvec = solver()->coPvec().get_const_ptr();
187  const Real* cupd = solver()->coPvec().delta().values();
188  const IdxSet& cidx = solver()->coPvec().idx();
189  const Real* lcb = solver()->lcBound().get_const_ptr();
190  const Real* ucb = solver()->ucBound().get_const_ptr();
191 
192  Real epsilon = solver()->epsilon();
193  Real val = max;
194  int pnum = -1;
195  int cnum = -1;
196 
197  SPxId enterId;
198  int i;
199  int j;
200  Real x;
201 
202  // PARALLEL the j loops could be parallelized
203  if (val > 0)
204  {
205  for( j = 0; j < pidx.size(); ++j )
206  {
207  i = pidx.index(j);
208  x = pupd[i];
209 
210  if (x > epsilon)
211  {
212  if (upb[i] < infinity)
213  {
214  Real y = (upb[i] - pvec[i] + delta) / x;
215 
216  if (y < val)
217  {
218  enterId = solver()->id(i);
219  val = y;
220  pnum = j;
221  }
222  }
223  }
224  else if (x < -epsilon)
225  {
226  if (lpb[i] > -infinity)
227  {
228  Real y = (lpb[i] - pvec[i] - delta) / x;
229 
230  if (y < val)
231  {
232  enterId = solver()->id(i);
233  val = y;
234  pnum = j;
235  }
236  }
237  }
238  }
239  for( j = 0; j < cidx.size(); ++j )
240  {
241  i = cidx.index(j);
242  x = cupd[i];
243 
244  if (x > epsilon)
245  {
246  if (ucb[i] < infinity)
247  {
248  Real y = (ucb[i] - cvec[i] + delta) / x;
249 
250  if (y < val)
251  {
252  enterId = solver()->coId(i);
253  val = y;
254  cnum = j;
255  }
256  }
257  }
258  else if (x < -epsilon)
259  {
260  if (lcb[i] > -infinity)
261  {
262  Real y = (lcb[i] - cvec[i] - delta) / x;
263 
264  if (y < val)
265  {
266  enterId = solver()->coId(i);
267  val = y;
268  cnum = j;
269  }
270  }
271  }
272  }
273  if (cnum >= 0)
274  {
275  i = cidx.index(cnum);
276  x = cupd[i];
277  val = (x > epsilon) ? ucb[i] : lcb[i];
278  val = (val - cvec[i]) / x;
279  }
280  else if (pnum >= 0)
281  {
282  i = pidx.index(pnum);
283  x = pupd[i];
284  val = (x > epsilon) ? upb[i] : lpb[i];
285  val = (val - pvec[i]) / x;
286  }
287  }
288  else
289  {
290  for( j = 0; j < pidx.size(); ++j )
291  {
292  i = pidx.index(j);
293  x = pupd[i];
294 
295  if (x > epsilon)
296  {
297  if (lpb[i] > -infinity)
298  {
299  Real y = (lpb[i] - pvec[i] - delta) / x;
300 
301  if (y > val)
302  {
303  enterId = solver()->id(i);
304  val = y;
305  pnum = j;
306  }
307  }
308  }
309  else if (x < -epsilon)
310  {
311  if (upb[i] < infinity)
312  {
313  Real y = (upb[i] - pvec[i] + delta) / x;
314 
315  if (y > val)
316  {
317  enterId = solver()->id(i);
318  val = y;
319  pnum = j;
320  }
321  }
322  }
323  }
324  for( j = 0; j < cidx.size(); ++j )
325  {
326  i = cidx.index(j);
327  x = cupd[i];
328 
329  if (x > epsilon)
330  {
331  if (lcb[i] > -infinity)
332  {
333  Real y = (lcb[i] - cvec[i] - delta) / x;
334 
335  if (y > val)
336  {
337  enterId = solver()->coId(i);
338  val = y;
339  cnum = j;
340  }
341  }
342  }
343  else if (x < -epsilon)
344  {
345  if (ucb[i] < infinity)
346  {
347  Real y = (ucb[i] - cvec[i] + delta) / x;
348 
349  if (y > val)
350  {
351  enterId = solver()->coId(i);
352  val = y;
353  cnum = j;
354  }
355  }
356  }
357  }
358  if (cnum >= 0)
359  {
360  i = cidx.index(cnum);
361  x = cupd[i];
362  val = (x < epsilon) ? ucb[i] : lcb[i];
363  val = (val - cvec[i]) / x;
364  }
365  else if (pnum >= 0)
366  {
367  i = pidx.index(pnum);
368  x = pupd[i];
369  val = (x < epsilon) ? upb[i] : lpb[i];
370  val = (val - pvec[i]) / x;
371  }
372  }
373 
374  if (enterId.isValid() && solver()->isBasic(enterId))
375  {
376  MSG_DEBUG( std::cout << "DDEFRT01 isValid() && isBasic(): max=" << max
377  << std::endl; )
378  if (cnum >= 0)
379  solver()->coPvec().delta().clearNum(cnum);
380  else
381  solver()->pVec().delta().clearNum(pnum);
382  return SPxDefaultRT::selectEnter(max, 0, false);
383  }
384 
385  MSG_DEBUG(
386  if( !enterId.isValid() )
387  std::cout << "DDEFRT02 !isValid(): max=" << max << ", x=" << x << std::endl;
388  )
389  max = val;
390 
391  return enterId;
392 }
393 
394 } // namespace soplex
SPxId coId(int i) const
id of i &#39;th covector.
Definition: spxsolver.h:1089
const Vector & ucBound() const
Definition: spxsolver.h:1389
virtual int selectLeave(Real &val, Real, bool)
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
Real delta
allowed bound violation
const Vector & lcBound() const
Definition: spxsolver.h:1410
#define ASSERT_WARN(prefix, expr)
Macro to turn some assertions into warnings.
Definition: spxdefines.h:74
virtual SPxId selectEnter(Real &val, int, bool)
const R * get_const_ptr() const
Conversion to C-style pointer.
Definition: vectorbase.h:453
const Vector & ubBound() const
upper bound for fVec.
Definition: spxsolver.h:1313
Generic Ids for LP rows or columns.Both SPxColIds and SPxRowIds may be treated uniformly as SPxIds: ...
Definition: spxid.h:85
UpdateVector & coPvec() const
copricing vector.
Definition: spxsolver.h:1370
double Real
Definition: spxdefines.h:215
const R * values() const
Returns array values.
Definition: ssvectorbase.h:299
#define MSG_DEBUG(x)
Definition: spxdefines.h:129
int size() const
returns the number of used indices.
Definition: idxset.h:124
const Vector & lbBound() const
lower bound for fVec.
Definition: spxsolver.h:1331
SPxId id(int i) const
id of i &#39;th vector.
Definition: spxsolver.h:1070
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1295
void clearNum(int n)
Sets n &#39;th nonzero element to 0 (index n must exist).
Definition: ssvectorbase.h:269
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1235
Real epsilon() const
values are considered to be 0.
Definition: spxsolver.h:758
Debugging, floating point type and parameter definitions.
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1450
const Vector & lpBound() const
Definition: spxsolver.h:1476
Everything should be within this namespace.
const IdxSet & idx() const
nonzero indices of update vector
Definition: updatevector.h:133
virtual SPxSolver * solver() const
returns loaded LP solver.
void setup()
Initializes nonzero indices for elements with absolute values above epsilon and sets all other elemen...
Definition: ssvectorbase.h:132
const Vector & upBound() const
Definition: spxsolver.h:1455
bool isValid() const
returns TRUE iff the id is a valid column or row identifier.
Definition: spxid.h:150
SSVector & delta()
update vector , writeable
Definition: updatevector.h:122
Textbook ratio test for SoPlex.
int index(int n) const
access n &#39;th index.
Definition: idxset.h:118
Set of indices.Class IdxSet provides a set of indices. At construction it must be given an array of i...
Definition: idxset.h:56