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-2016 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);
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
const R * values() const
Returns array values.
Definition: ssvectorbase.h:288
const IdxSet & idx() const
nonzero indices of update vector
Definition: updatevector.h:133
bool isValid() const
returns TRUE iff the id is a valid column or row identifier.
Definition: spxid.h:150
Real delta
allowed bound violation
const Vector & lbBound() const
lower bound for fVec.
Definition: spxsolver.h:1220
const R * get_const_ptr() const
Conversion to C-style pointer.
Definition: vectorbase.h:412
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1184
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1339
const Vector & ubBound() const
upper bound for fVec.
Definition: spxsolver.h:1202
SPxId coId(int i) const
id of i &#39;th covector.
Definition: spxsolver.h:978
#define ASSERT_WARN(prefix, expr)
Macro to turn some assertions into warnings.
Definition: spxdefines.h:72
virtual SPxId selectEnter(Real &val, int)
int index(int n) const
access n &#39;th index.
Definition: idxset.h:118
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:1259
double Real
SOPLEX_DEBUG.
Definition: spxdefines.h:200
#define MSG_DEBUG(x)
Definition: spxdefines.h:127
int size() const
returns the number of used indices.
Definition: idxset.h:124
virtual int selectLeave(Real &val, Real)
void clearNum(int n)
Sets n &#39;th nonzero element to 0 (index n must exist).
Definition: ssvectorbase.h:258
const Vector & lcBound() const
Definition: spxsolver.h:1299
const Vector & upBound() const
Definition: spxsolver.h:1344
Debugging, floating point type and parameter definitions.
Everything should be within this namespace.
void setup()
Initializes nonzero indices for elements with absolute values above epsilon and sets all other elemen...
Definition: ssvectorbase.h:132
SPxId id(int i) const
id of i &#39;th vector.
Definition: spxsolver.h:959
const Vector & lpBound() const
Definition: spxsolver.h:1365
Real epsilon() const
values are considered to be 0.
Definition: spxsolver.h:670
const Real infinity
Definition: spxdefines.cpp:26
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1124
SSVector & delta()
update vector , writeable
Definition: updatevector.h:122
Textbook ratio test for SoPlex.
const Vector & ucBound() const
Definition: spxsolver.h:1278
Set of indices.Class IdxSet provides a set of indices. At construction it must be given an array of i...
Definition: idxset.h:56
virtual SPxSolver * solver() const
returns loaded LP solver.