Scippy

SoPlex

Sequential object-oriented simPlex

spxbounds.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 
22 namespace soplex
23 {
24 /** Setting up the feasiblity bound for normal primal variables is
25  straightforward. However, slack variables need some more details
26  on how we treate them. This is slightly different from usual
27  textbook versions. Let \f$l_i \le A_i^T x \le u_i\f$. This can be
28  transformed to \f$A_i^Tx + s_i = 0\f$, with \f$-u_i \le s_i \le
29  -l_i\f$. Hence, with this definition of slack variables \f$s_i\f$, we
30  can directly use vectors \f$l\f$ and \f$u\f$ as feasibility bounds.
31  */
33 {
34 
37 
38  if (rep() == ROW)
39  {
40  theURbound = rhs();
41  theLRbound = lhs();
42  }
43  else
44  {
45  theURbound = lhs();
46  theLRbound = rhs();
47  theURbound *= -1.0;
48  theLRbound *= -1.0;
49  }
50 }
51 
52 /** Seting up the basis for dual simplex requires to install upper and lower
53  feasibility bounds for dual variables (|Lbound| and |Ubound|). Here is a
54  list of how these must be set for inequalities of type \f$l \le a^Tx \le u\f$:
55 
56  \f[
57  \begin{tabular}{cccc}
58  $l$ & $u$ & |Lbound| & |Ubound| \\
59  \hline
60  $-\infty=l$ & $u=\infty$ & 0 & 0 \\
61  $-\infty<l$ & $u=\infty$ & 0 & $\infty$ \\
62  $-\infty=l$ & $u<\infty$ & $-\infty$ & 0 \\
63  \multicolumn{2}{c}{
64  $-\infty<l \ne u<\infty$} & 0 & 0 \\
65  \multicolumn{2}{c}{
66  $-\infty<l = u<\infty$} & $-\infty$ & $\infty$ \\
67  \end{tabular}
68  \f]
69  The case \f$l = -\infty\f$, \f$u = \infty\f$ occurs for unbounded primal variables.
70  Such must be treated differently from the general case.
71 
72  Given possible upper and lower bounds to a dual variable with |Status stat|,
73  this function clears the bounds according to |stat| by setting them to
74  \f$\infty\f$ or \f$-\infty\f$, respectively.
75  */
78  Real& upp,
79  Real& lw) const
80 {
81 
82  switch (stat)
83  {
86  upp = infinity;
87  lw = -infinity;
88  break;
91  upp = infinity;
92  break;
95  lw = -infinity;
96  break;
97 
98  default:
99  break;
100  }
101 }
102 
104 {
105 
106  assert(rep() == COLUMN);
107 
108  const SPxBasis::Desc& ds = desc();
109 
110  int i;
111 
112  for(i = 0; i < nRows(); ++i)
113  {
114  theURbound[i] = maxRowObj(i);
115  theLRbound[i] = maxRowObj(i);
116 
118  }
119 
120  for(i = 0; i < nCols(); ++i)
121  {
122  theUCbound[i] = -maxObj(i);
123  theLCbound[i] = -maxObj(i);
124 
125  // exchanged ... due to definition of slacks!
127 
128  theUCbound[i] *= -1.0;
129  theLCbound[i] *= -1.0;
130  }
131 }
132 
134 {
135 
136  assert(rep() == ROW);
137 
138  int i;
139 
140  for(i = 0; i < nRows(); ++i)
141  {
142  theURbound[i] = 0.0;
143  theLRbound[i] = 0.0;
144 
146  }
147 
148  for(i = 0; i < nCols(); ++i)
149  {
150  theUCbound[i] = 0.0;
151  theLCbound[i] = 0.0;
152 
154  }
155 }
156 
157 
158 /** This sets up the bounds for basic variables for entering simplex algorithms.
159  It requires, that all upper lower feasibility bounds have allready been
160  setup. Method |setEnterBound4Row(i, n)| does so for the |i|-th basis
161  variable being row index |n|. Equivalently, method
162  |setEnterBound4Col(i, n)| does so for the |i|-th basis variable being
163  column index |n|.
164  */
166 {
167  assert(baseId(i).isSPxRowId());
168  assert(number(SPxRowId(baseId(i))) == n);
169  switch (desc().rowStatus(n))
170  {
172  theLBbound[i] = -infinity;
173  theUBbound[i] = theURbound[n];
174  break;
176  theLBbound[i] = theLRbound[n];
177  theUBbound[i] = infinity;
178  break;
179 
180  default:
181  theUBbound[i] = theURbound[n];
182  theLBbound[i] = theLRbound[n];
183  break;
184  }
185 }
186 
188 {
189  assert(baseId(i).isSPxColId());
190  assert(number(SPxColId(baseId(i))) == n);
191  switch (desc().colStatus(n))
192  {
194  theLBbound[i] = -infinity;
195  theUBbound[i] = theUCbound[n];
196  break;
198  theLBbound[i] = theLCbound[n];
199  theUBbound[i] = infinity;
200  break;
201 
202  default:
203  theUBbound[i] = theUCbound[n];
204  theLBbound[i] = theLCbound[n];
205  break;
206  }
207 }
208 
210 {
211 
212  for (int i = 0; i < dim(); ++i)
213  {
214  SPxId base_id = baseId(i);
215 
216  if (base_id.isSPxRowId())
217  setEnterBound4Row(i, number(SPxRowId(base_id)));
218  else
219  setEnterBound4Col(i, number(SPxColId(base_id)));
220  }
221 }
222 
223 
224 /** This sets up the bounds for basic variables for leaving simplex algorithms.
225  While method |setLeaveBound4Row(i,n)| does so for the |i|-th basic variable
226  being the |n|-th row, |setLeaveBound4Col(i,n)| does so for the |i|-th basic
227  variable being the |n|-th column.
228  */
230 {
231  assert(baseId(i).isSPxRowId());
232  assert(number(SPxRowId(baseId(i))) == n);
233  switch (desc().rowStatus(n))
234  {
236  theLBbound[i] = -infinity;
237  theUBbound[i] = -maxRowObj(n);
238  break;
240  theLBbound[i] = -maxRowObj(n);
241  theUBbound[i] = infinity;
242  break;
244  theLBbound[i] = -infinity;
245  theUBbound[i] = infinity;
246  break;
248  theLBbound[i] = -maxRowObj(n);
249  theUBbound[i] = -maxRowObj(n);
250  break;
251 
252  default:
253  assert(rep() == COLUMN);
254  theLBbound[i] = -rhs(n); // slacks !
255  theUBbound[i] = -lhs(n); // slacks !
256  break;
257  }
258 }
259 
261 {
262 
263  assert(baseId(i).isSPxColId());
264  assert(number(SPxColId(baseId(i))) == n);
265 
266  switch (desc().colStatus(n))
267  {
269  theLBbound[i] = -infinity;
270  theUBbound[i] = 0;
271  break;
273  theLBbound[i] = 0;
274  theUBbound[i] = infinity;
275  break;
277  theLBbound[i] = -infinity;
278  theUBbound[i] = infinity;
279  break;
281  theLBbound[i] = theUBbound[i] = 0;
282  break;
283 
284  default:
285  theUBbound[i] = SPxLP::upper(n);
286  theLBbound[i] = SPxLP::lower(n);
287  break;
288  }
289 }
290 
292 {
293 
294  for (int i = 0; i < dim(); ++i)
295  {
296  SPxId base_id = baseId(i);
297 
298  if (base_id.isSPxRowId())
299  setLeaveBound4Row(i, number(SPxRowId(base_id)));
300  else
301  setLeaveBound4Col(i, number(SPxColId(base_id)));
302  }
303 }
304 
306 {
307 
308  if (type() == ENTER)
309  {
310  Real viol_max = (1 + iterCount) * entertol();
311  int nlinesprinted = 0;
312  int m = dim();
313 
314  for(int i = 0; i < m; ++i )
315  {
316  // Minor bound violations happen frequently, so print these
317  // warnings only with verbose level INFO2 and higher.
318  if ((*theFvec)[i] > theUBbound[i] + viol_max) //@ && theUBbound[i] != theLBbound[i])
319  {
320  MSG_INFO2( (*spxout), (*spxout) << "WBOUND01 Invalid upper enter bound " << i
321  << " viol_max: " << viol_max
322  << " Fvec: " << (*theFvec)[i]
323  << " UBbound: "<< theUBbound[i] << std::endl; )
324  nlinesprinted++;
325  }
326  if ((*theFvec)[i] < theLBbound[i] - viol_max) //@ && theUBbound[i] != theLBbound[i])
327  {
328  MSG_INFO2( (*spxout), (*spxout) << "WBOUND02 Invalid lower enter bound " << i
329  << " viol_max: " << viol_max
330  << " Fvec: " << (*theFvec)[i]
331  << " LBbound: "<< theLBbound[i] << std::endl; )
332  nlinesprinted++;
333  }
334  if( nlinesprinted >= 3 )
335  {
336  MSG_INFO2( (*spxout), (*spxout) << "WBOUND10 suppressing further warnings of type WBOUND{01,02} in this round" << std::endl );
337  break;
338  }
339  }
340  }
341  else
342  {
343  Real viol_max = (1 + iterCount) * leavetol();
344  int nlinesprinted = 0;
345  int m = dim();
346  int n = coDim();
347 
348  for(int i = 0; i < m; ++i )
349  {
350  if ((*theCoPvec)[i] > (*theCoUbound)[i] + viol_max) // && (*theCoUbound)[i] != (*theCoLbound)[i])
351  {
352  MSG_INFO2( (*spxout), (*spxout) << "WBOUND03 Invalid upper cobound " << i
353  << " viol_max: " << viol_max
354  << " CoPvec: " << (*theCoPvec)[i]
355  << " CoUbound: "<< (*theCoUbound)[i] << std::endl; )
356  nlinesprinted++;
357  }
358  if ((*theCoPvec)[i] < (*theCoLbound)[i] - viol_max) // && (*theCoUbound)[i] != (*theCoLbound)[i])
359  {
360  MSG_INFO2( (*spxout), (*spxout) << "WBOUND04 Invalid lower cobound " << i
361  << " viol_max: " << viol_max
362  << " CoPvec: " << (*theCoPvec )[i]
363  << " CoLbound: " << (*theCoLbound)[i]
364  << std::endl; )
365  nlinesprinted++;
366  }
367  if( nlinesprinted >= 3 )
368  {
369  MSG_INFO2( (*spxout), (*spxout) << "WBOUND11 suppressing further warnings of type WBOUND{03,04} in this round" << std::endl );
370  break;
371  }
372  }
373 
374  nlinesprinted = 0;
375  for(int i = 0; i < n; ++i )
376  {
377  if ((*thePvec)[i] > (*theUbound)[i] + viol_max) // && (*theUbound)[i] != (*theLbound)[i])
378  {
379  MSG_INFO2( (*spxout), (*spxout) << "WBOUND05 Invalid upper bound " << i
380  << " viol_max: " << viol_max
381  << " Pvec: " << (*thePvec)[i]
382  << " Ubound: " << (*theUbound)[i] << std::endl; )
383  nlinesprinted++;
384  }
385  if ((*thePvec)[i] < (*theLbound)[i] - viol_max) // && (*theUbound)[i] != (*theLbound)[i])
386  {
387  MSG_INFO2( (*spxout), (*spxout) << "WBOUND06 Invalid lower bound " << i
388  << " viol_max: " << viol_max
389  << " Pvec: " << (*thePvec)[i]
390  << " Lbound: " << (*theLbound)[i] << std::endl; )
391  nlinesprinted++;
392  }
393  if( nlinesprinted >= 3 )
394  {
395  MSG_INFO2( (*spxout), (*spxout) << "WBOUND12 suppressing further warnings of type WBOUND{05,06} in this round" << std::endl );
396  break;
397  }
398  }
399  }
400 }
401 } // namespace soplex