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-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 <assert.h>
17 #include <iostream>
18 
19 #include "soplex/spxdefines.h"
20 #include "soplex/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 
94  if(leave >= 0)
95  {
96  x = upd[leave];
97 
98  // BH 2005-11-30: It may well happen that the basis is degenerate and the
99  // selected leaving variable is (at most delta) beyond its bound. (This
100  // happens for instance on LP/netlib/adlittle.mps with setting -r -t0.)
101  // In that case we do a pivot step with length zero to avoid difficulties.
102  if((x > epsilon && vec[leave] >= ub[leave]) ||
103  (x < -epsilon && vec[leave] <= lb[leave]))
104  {
105  val = 0.0;
106  }
107  else
108  {
109  val = (x > epsilon) ? ub[leave] : lb[leave];
110  val = (val - vec[leave]) / x;
111  }
112  }
113 
114  ASSERT_WARN("WDEFRT01", val > -epsilon);
115  }
116  else
117  {
118  for(j = 0; j < idx.size(); ++j)
119  {
120  i = idx.index(j);
121  x = upd[i];
122 
123  if(x < -epsilon)
124  {
125  if(ub[i] < infinity)
126  {
127  Real y = (ub[i] - vec[i] + delta) / x;
128 
129  if(y > val)
130  {
131  leave = i;
132  val = y;
133  }
134  }
135  }
136  else if(x > epsilon)
137  {
138  if(lb[i] > -infinity)
139  {
140  Real y = (lb[i] - vec[i] - delta) / x;
141 
142  if(y > val)
143  {
144  leave = i;
145  val = y;
146  }
147  }
148  }
149  }
150 
151  if(leave >= 0)
152  {
153  x = upd[leave];
154 
155  // See comment above.
156  if((x < -epsilon && vec[leave] >= ub[leave]) ||
157  (x > epsilon && vec[leave] <= lb[leave]))
158  {
159  val = 0.0;
160  }
161  else
162  {
163  val = (x < epsilon) ? ub[leave] : lb[leave];
164  val = (val - vec[leave]) / x;
165  }
166  }
167 
168  ASSERT_WARN("WDEFRT02", val < epsilon);
169  }
170 
171  return leave;
172 }
173 
174 /**
175  Here comes the ratio test. It is assumed that theCoPvec.delta() and
176  theCoPvec.idx() have been setup correctly!
177  */
179 {
180  solver()->coPvec().delta().setup();
181  solver()->pVec().delta().setup();
182 
183  const Real* pvec = solver()->pVec().get_const_ptr();
184  const Real* pupd = solver()->pVec().delta().values();
185  const IdxSet& pidx = solver()->pVec().idx();
186  const Real* lpb = solver()->lpBound().get_const_ptr();
187  const Real* upb = solver()->upBound().get_const_ptr();
188 
189  const Real* cvec = solver()->coPvec().get_const_ptr();
190  const Real* cupd = solver()->coPvec().delta().values();
191  const IdxSet& cidx = solver()->coPvec().idx();
192  const Real* lcb = solver()->lcBound().get_const_ptr();
193  const Real* ucb = solver()->ucBound().get_const_ptr();
194 
195  Real epsilon = solver()->epsilon();
196  Real val = max;
197  int pnum = -1;
198  int cnum = -1;
199 
200  SPxId enterId;
201  int i;
202  int j;
203  Real x;
204 
205  // PARALLEL the j loops could be parallelized
206  if(val > 0)
207  {
208  for(j = 0; j < pidx.size(); ++j)
209  {
210  i = pidx.index(j);
211  x = pupd[i];
212 
213  if(x > epsilon)
214  {
215  if(upb[i] < infinity)
216  {
217  Real y = (upb[i] - pvec[i] + delta) / x;
218 
219  if(y < val)
220  {
221  enterId = solver()->id(i);
222  val = y;
223  pnum = j;
224  }
225  }
226  }
227  else if(x < -epsilon)
228  {
229  if(lpb[i] > -infinity)
230  {
231  Real y = (lpb[i] - pvec[i] - delta) / x;
232 
233  if(y < val)
234  {
235  enterId = solver()->id(i);
236  val = y;
237  pnum = j;
238  }
239  }
240  }
241  }
242 
243  for(j = 0; j < cidx.size(); ++j)
244  {
245  i = cidx.index(j);
246  x = cupd[i];
247 
248  if(x > epsilon)
249  {
250  if(ucb[i] < infinity)
251  {
252  Real y = (ucb[i] - cvec[i] + delta) / x;
253 
254  if(y < val)
255  {
256  enterId = solver()->coId(i);
257  val = y;
258  cnum = j;
259  }
260  }
261  }
262  else if(x < -epsilon)
263  {
264  if(lcb[i] > -infinity)
265  {
266  Real y = (lcb[i] - cvec[i] - delta) / x;
267 
268  if(y < val)
269  {
270  enterId = solver()->coId(i);
271  val = y;
272  cnum = j;
273  }
274  }
275  }
276  }
277 
278  if(cnum >= 0)
279  {
280  i = cidx.index(cnum);
281  x = cupd[i];
282  val = (x > epsilon) ? ucb[i] : lcb[i];
283  val = (val - cvec[i]) / x;
284  }
285  else if(pnum >= 0)
286  {
287  i = pidx.index(pnum);
288  x = pupd[i];
289  val = (x > epsilon) ? upb[i] : lpb[i];
290  val = (val - pvec[i]) / x;
291  }
292  }
293  else
294  {
295  for(j = 0; j < pidx.size(); ++j)
296  {
297  i = pidx.index(j);
298  x = pupd[i];
299 
300  if(x > epsilon)
301  {
302  if(lpb[i] > -infinity)
303  {
304  Real y = (lpb[i] - pvec[i] - delta) / x;
305 
306  if(y > val)
307  {
308  enterId = solver()->id(i);
309  val = y;
310  pnum = j;
311  }
312  }
313  }
314  else if(x < -epsilon)
315  {
316  if(upb[i] < infinity)
317  {
318  Real y = (upb[i] - pvec[i] + delta) / x;
319 
320  if(y > val)
321  {
322  enterId = solver()->id(i);
323  val = y;
324  pnum = j;
325  }
326  }
327  }
328  }
329 
330  for(j = 0; j < cidx.size(); ++j)
331  {
332  i = cidx.index(j);
333  x = cupd[i];
334 
335  if(x > epsilon)
336  {
337  if(lcb[i] > -infinity)
338  {
339  Real y = (lcb[i] - cvec[i] - delta) / x;
340 
341  if(y > val)
342  {
343  enterId = solver()->coId(i);
344  val = y;
345  cnum = j;
346  }
347  }
348  }
349  else if(x < -epsilon)
350  {
351  if(ucb[i] < infinity)
352  {
353  Real y = (ucb[i] - cvec[i] + delta) / x;
354 
355  if(y > val)
356  {
357  enterId = solver()->coId(i);
358  val = y;
359  cnum = j;
360  }
361  }
362  }
363  }
364 
365  if(cnum >= 0)
366  {
367  i = cidx.index(cnum);
368  x = cupd[i];
369  val = (x < epsilon) ? ucb[i] : lcb[i];
370  val = (val - cvec[i]) / x;
371  }
372  else if(pnum >= 0)
373  {
374  i = pidx.index(pnum);
375  x = pupd[i];
376  val = (x < epsilon) ? upb[i] : lpb[i];
377  val = (val - pvec[i]) / x;
378  }
379  }
380 
381  if(enterId.isValid() && solver()->isBasic(enterId))
382  {
383  MSG_DEBUG(std::cout << "DDEFRT01 isValid() && isBasic(): max=" << max
384  << std::endl;)
385 
386  if(cnum >= 0)
387  solver()->coPvec().delta().clearNum(cnum);
388  else if(pnum >= 0)
389  solver()->pVec().delta().clearNum(pnum);
390 
391  return SPxDefaultRT::selectEnter(max, 0, false);
392  }
393 
394  MSG_DEBUG(
395 
396  if(!enterId.isValid())
397  std::cout << "DDEFRT02 !isValid(): max=" << max << ", x=" << x << std::endl;
398  )
399  max = val;
400 
401  return enterId;
402 }
403 
404 } // namespace soplex
SPxId coId(int i) const
id of i &#39;th covector.
Definition: spxsolver.h:1117
const Vector & ucBound() const
Definition: spxsolver.h:1417
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:1438
#define ASSERT_WARN(prefix, expr)
Macro to turn some assertions into warnings.
Definition: spxdefines.h:77
virtual SPxId selectEnter(Real &val, int, bool)
const R * get_const_ptr() const
Conversion to C-style pointer.
Definition: vectorbase.h:455
const Vector & ubBound() const
upper bound for fVec.
Definition: spxsolver.h:1341
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:1398
double Real
Definition: spxdefines.h:218
const R * values() const
Returns array values.
Definition: ssvectorbase.h:300
#define MSG_DEBUG(x)
Definition: spxdefines.h:132
int size() const
returns the number of used indices.
Definition: idxset.h:124
const Vector & lbBound() const
lower bound for fVec.
Definition: spxsolver.h:1359
SPxId id(int i) const
id of i &#39;th vector.
Definition: spxsolver.h:1098
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1323
void clearNum(int n)
Sets n &#39;th nonzero element to 0 (index n must exist).
Definition: ssvectorbase.h:270
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1263
Real epsilon() const
values are considered to be 0.
Definition: spxsolver.h:784
Debugging, floating point type and parameter definitions.
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1478
const Vector & lpBound() const
Definition: spxsolver.h:1504
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:133
const Vector & upBound() const
Definition: spxsolver.h:1483
bool isValid() const
returns TRUE iff the id is a valid column or row identifier.
Definition: spxid.h:151
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