Scippy

SoPlex

Sequential object-oriented simPlex

spxfastrt.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 <stdio.h>
18 
19 #include "spxdefines.h"
20 #include "spxfastrt.h"
21 
22 
23 /*
24  Here comes our implementation of the Harris procedure improved by shifting
25  bounds. The basic idea is to allow a slight infeasibility within |delta| to
26  allow for more freedom when selecting the leaving variable. This freedom
27  may then be used for selecting numerically stable variables yielding great
28  improvements.
29 
30  The algorithms operates in two phases. In a first phase, the maximum value
31  |val| is determined, when infeasibility within |delta| is allowed. In the second
32  phase, between all variables with value < |val| the one is selected which
33  has the largest update vector component. However, this may not
34  always yield an improvement. In that case, we shift the variable towards
35  infeasibility and retry. This avoids cycling in the shifted LP.
36  */
37 
38 namespace soplex
39 {
40 
41 #define MINSTAB 1e-5
42 #define LOWSTAB 1e-10
43 #define TRIES 2
44 #define SHORT 1e-5
45 #define DELTA_SHIFT 1e-5
46 #define EPSILON 1e-10
47 
49 {
50  // epsilon = thesolver->epsilon();
51  epsilon = EPSILON;
52  /*
53  if(thesolver->basis().stability() < 1e-4)
54  epsilon *= 1e-4 / thesolver->basis().stability();
55  */
56 }
57 
59 {
60  /*
61  if((delta > 1.99 * DELTA_SHIFT && thesolver->theShift < 1e-4) ||
62  (delta > 1e-4 && thesolver->theShift > 1e-4))
63  */
64  // if(delta > 1.99 * DELTA_SHIFT)
65  if (fastDelta >= delta + DELTA_SHIFT)
66  {
68  if (fastDelta > 1e-4)
69  fastDelta -= 2 * DELTA_SHIFT;
70  }
71 
72  if (minStab < MINSTAB)
73  {
74  minStab /= 0.90;
75  if (minStab < 1e-6)
76  minStab /= 0.90;
77  }
78 }
79 
81 {
82  minStab *= 0.95;
83  fastDelta += 3 * DELTA_SHIFT;
84  // delta += 2 * (thesolver->theShift > delta) * DELTA_SHIFT;
85 }
86 
88 {
89  if (maxabs < 1000.0)
90  return minStab;
91  return maxabs*minStab / 1000.0;
92 }
93 
94 /* The code below implements phase 1 of the ratio test. It differs from the description in the
95  * Ph.D. thesis page 57 as follows: It uses \f$\delta_i = d_i - s_i - \delta\f$ if \f$d_i > s_i\f$.
96  *
97  * This change leads to the following behavior of the source code. Consider the first case (x >
98  * epsilon, u < infinity): If u - vec[i] <= 0, vec[i] violates the upper bound. In the Harris ratio
99  * test, we would compute (u - vec[i] + delta)/upd[i]. The code computes instead delta/upd[i].
100  */
102  Real& val, /* on return: maximum step length */
103  Real& maxabs, /* on return: maximum absolute value in upd vector */
104  UpdateVector& update,
105  const Vector& lowBound,
106  const Vector& upBound,
107  int start,
108  int incr) const
109 {
110  int i, sel;
111  Real x, y, max;
112  Real u, l;
113  bool leaving = m_type == SPxSolver::LEAVE;
114 
115  Real mabs = maxabs;
116 
117  const Real* up = upBound.get_const_ptr();
118  const Real* low = lowBound.get_const_ptr();
119  const Real* vec = update.get_const_ptr();
120  const Real* upd = update.delta().values();
121  const int* idx = update.delta().indexMem();
122 
123  sel = -1;
124  max = val;
125 
126  if (update.delta().isSetup())
127  {
128  const int* last = idx + update.delta().size();
129  for (idx += start; idx < last; idx += incr)
130  {
131  i = *idx;
132 
133  /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
134  if( leaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) )
135  continue;
136 
137  x = upd[i];
138 
139  if (x > epsilon)
140  {
141  // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
142  mabs = (x > mabs) ? x : mabs;
143  u = up[i];
144  if (u < infinity)
145  {
146  y = u - vec[i];
147  if (y <= 0)
148  x = fastDelta / x;
149  else
150  x = (y + fastDelta) / x;
151 
152  if (x < max)
153  {
154  max = x;
155  sel = i;
156  }
157  }
158  }
159  else if (x < -epsilon)
160  {
161  // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
162  mabs = (-x > mabs) ? -x : mabs;
163  l = low[i];
164  if (l > -infinity)
165  {
166  y = l - vec[i];
167  if ( y >= 0 )
168  x = - fastDelta / x;
169  else
170  x = ( y - fastDelta ) / x;
171 
172  if (x < max)
173  {
174  max = x;
175  sel = i;
176  }
177  }
178  }
179  }
180  }
181  else
182  {
183  /* In this case, the indices of the semi-sparse vector update.delta() are not set up and are filled below. */
184  int* l_idx = update.delta().altIndexMem();
185  Real* uval = update.delta().altValues();
186  const Real* uend = uval + update.dim();
187  assert( uval == upd );
188 
189  for (i = 0; uval < uend; ++uval, ++i)
190  {
191  x = *uval;
192  if (x != 0.0)
193  {
194  if (x >= -epsilon && x <= epsilon)
195  {
196  *uval = 0.0;
197  continue;
198  }
199  else
200  *l_idx++ = i;
201 
202  /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
203  if( leaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) )
204  continue;
205 
206  if (x > epsilon)
207  {
208  mabs = (x > mabs) ? x : mabs;
209  u = up[i];
210  if (u < infinity)
211  {
212  y = u - vec[i];
213  if (y <= 0)
214  x = fastDelta / x;
215  else
216  x = (y + fastDelta) / x;
217 
218  if (x < max)
219  {
220  max = x;
221  sel = i;
222  }
223  }
224  }
225  else if (x < -epsilon)
226  {
227  mabs = (-x > mabs) ? -x : mabs;
228  l = low[i];
229  if (l > -infinity)
230  {
231  y = l - vec[i];
232  if ( y >= 0 )
233  x = - fastDelta / x;
234  else
235  x = ( y - fastDelta ) / x;
236 
237  if (x < max)
238  {
239  max = x;
240  sel = i;
241  }
242  }
243  }
244  }
245  }
246  update.delta().setSize(int(l_idx - update.delta().indexMem()));
247  update.delta().forceSetup();
248  }
249 
250  val = max;
251  maxabs = mabs;
252  return sel;
253 }
254 
255 /* See maxDelta() */
257  Real& val,
258  Real& maxabs,
259  UpdateVector& update,
260  const Vector& lowBound,
261  const Vector& upBound,
262  int start,
263  int incr) const
264 {
265  int i, sel;
266  Real x, y, max;
267  Real u, l;
268  bool leaving = m_type == SPxSolver::LEAVE;
269 
270  Real mabs = maxabs;
271 
272  const Real* up = upBound.get_const_ptr();
273  const Real* low = lowBound.get_const_ptr();
274  const Real* vec = update.get_const_ptr();
275  const Real* upd = update.delta().values();
276  const int* idx = update.delta().indexMem();
277 
278  sel = -1;
279  max = val;
280 
281  if (update.delta().isSetup())
282  {
283  const int* last = idx + update.delta().size();
284  for (idx += start; idx < last; idx += incr)
285  {
286  i = *idx;
287  x = upd[i];
288 
289  /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
290  if( leaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) )
291  continue;
292 
293  if (x > epsilon)
294  {
295  // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
296  mabs = (x > mabs) ? x : mabs;
297  l = low[i];
298  if (l > -infinity)
299  {
300  y = l - vec[i];
301  if ( y >= 0 )
302  x = - fastDelta / x;
303  else
304  x = ( y - fastDelta ) / x;
305 
306  if (x > max)
307  {
308  max = x;
309  sel = i;
310  }
311  }
312  }
313  else if (x < -epsilon)
314  {
315  // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
316  mabs = (-x > mabs) ? -x : mabs;
317  u = up[i];
318  if (u < infinity)
319  {
320  y = u - vec[i];
321  if (y <= 0)
322  x = fastDelta / x;
323  else
324  x = (y + fastDelta) / x;
325 
326  if (x > max)
327  {
328  max = x;
329  sel = i;
330  }
331  }
332  }
333  }
334  }
335  else
336  {
337  /* In this case, the indices of the semi-sparse vector update.delta() are not set up and are filled below. */
338  int* l_idx = update.delta().altIndexMem();
339  Real* uval = update.delta().altValues();
340  const Real* uend = uval + update.dim();
341  assert( uval == upd );
342 
343  for (i = 0; uval < uend; ++uval, ++i)
344  {
345  x = *uval;
346 
347  if (x != 0.0)
348  {
349  if (x >= -epsilon && x <= epsilon)
350  {
351  *uval = 0.0;
352  continue;
353  }
354  else
355  *l_idx++ = i;
356 
357  /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
358  if( leaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) )
359  continue;
360 
361  if (x > epsilon)
362  {
363  mabs = (x > mabs) ? x : mabs;
364  l = low[i];
365  if (l > -infinity)
366  {
367  y = l - vec[i];
368  if ( y >= 0 )
369  x = - fastDelta / x;
370  else
371  x = ( y - fastDelta ) / x;
372 
373  if (x > max)
374  {
375  max = x;
376  sel = i;
377  }
378  }
379  }
380  else if (x < -epsilon)
381  {
382  mabs = (-x > mabs) ? -x : mabs;
383  u = up[i];
384  if (u < infinity)
385  {
386  y = u - vec[i];
387  if (y <= 0)
388  x = fastDelta / x;
389  else
390  x = (y + fastDelta) / x;
391 
392  if (x > max)
393  {
394  max = x;
395  sel = i;
396  }
397  }
398  }
399  }
400  }
401  update.delta().setSize(int(l_idx - update.delta().indexMem()));
402  update.delta().forceSetup();
403  }
404 
405  val = max;
406  maxabs = mabs;
407 
408  return sel;
409 }
410 
412  Real& val,
413  Real& maxabs)
414 {
415  assert(m_type == SPxSolver::ENTER);
416  return maxDelta(val, maxabs,
417  thesolver->fVec(), thesolver->lbBound(), thesolver->ubBound(), 0, 1);
418 }
419 
421  Real& val,
422  Real& maxabs)
423 {
424  assert(m_type == SPxSolver::ENTER);
425  return minDelta(val, maxabs,
426  thesolver->fVec(), thesolver->lbBound(), thesolver->ubBound(), 0, 1);
427 }
428 
430  int& nr,
431  Real& max, /* on return: maximum step length */
432  Real& maxabs) /* on return: maximum absolute value in delta vector */
433 {
434  /* The following cause side effects on coPvec and pVec - both changes may be needed later in
435  maxSelect(). We can therefore not move the first function after the (indp >= 0) check. */
436  iscoid = true;
437  int indc = maxDelta(max, maxabs,
439  iscoid = false;
440  int indp = maxDelta(max, maxabs,
441  thesolver->pVec(), thesolver->lpBound(), thesolver->upBound(), 0, 1);
442 
443  if (indp >= 0)
444  {
445  nr = indp;
446  return thesolver->id(indp);
447  }
448  if (indc >= 0)
449  {
450  nr = indc;
451  return thesolver->coId(indc);
452  }
453  nr = -1;
454  return SPxId();
455 }
456 
458  int& nr,
459  Real& max,
460  Real& maxabs)
461 {
462  /* The following cause side effects on coPvec and pVec - both changes may be needed later in
463  minSelect(). We can therefore not move the first function after the (indp >= 0) check. */
464  iscoid = true;
465  const int indc = minDelta(max, maxabs,
467  iscoid = false;
468  const int indp = minDelta(max, maxabs,
469  thesolver->pVec(), thesolver->lpBound(), thesolver->upBound(), 0, 1);
470 
471  if (indp >= 0)
472  {
473  nr = indp;
474  return thesolver->id(indp);
475  }
476  if (indc >= 0)
477  {
478  nr = indc;
479  return thesolver->coId(indc);
480  }
481  nr = -1;
482  return SPxId();
483 }
484 
485 /* \p best returns the minimum update value such that the corresponding value of \p upd.delta() is
486  * at least \p stab and the update value is smaller than \p max. If no valid update value has been
487  * found \p bestDelta returns the slack to the bound corresponding to the index used for \p best. */
489  Real& val,
490  Real& stab,
491  Real& best,
492  Real& bestDelta,
493  Real max,
494  const UpdateVector& update,
495  const Vector& lowBound,
496  const Vector& upBound,
497  int start,
498  int incr) const
499 {
500  int i;
501  Real x, y;
502  bool leaving = m_type == SPxSolver::LEAVE;
503 
504  const Real* up = upBound.get_const_ptr();
505  const Real* low = lowBound.get_const_ptr();
506  const Real* vec = update.get_const_ptr();
507  const Real* upd = update.delta().values();
508  const int* idx = update.delta().indexMem();
509  const int* last = idx + update.delta().size();
510 
511  int nr = -1;
512  int bestNr = -1;
513 
514  for (idx += start; idx < last; idx += incr)
515  {
516  i = *idx;
517  x = upd[i];
518 
519  // in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables
520  if( leaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) )
521  continue;
522 
523  if (x > stab)
524  {
525  y = (low[i] - vec[i]) / x;
526 
527  if (y >= max)
528  {
529  val = y;
530  nr = i;
531  stab = x;
532  }
533  else if (y < best)
534  {
535  best = y;
536  bestNr = i;
537  }
538  }
539  else if (x < -stab)
540  {
541  y = (up[i] - vec[i]) / x;
542  if (y >= max)
543  {
544  val = y;
545  nr = i;
546  stab = -x;
547  }
548  else if (y < best)
549  {
550  best = y;
551  bestNr = i;
552  }
553  }
554  }
555 
556  if (nr < 0 && bestNr > 0)
557  {
558  if (upd[bestNr] < 0)
559  bestDelta = up[bestNr] - vec[bestNr];
560  else
561  bestDelta = vec[bestNr] - low[bestNr];
562  }
563  return nr;
564 }
565 
566 /* See minSelect() */
568  Real& val,
569  Real& stab,
570  Real& best,
571  Real& bestDelta,
572  Real max,
573  const UpdateVector& update,
574  const Vector& lowBound,
575  const Vector& upBound,
576  int start,
577  int incr) const
578 {
579  int i;
580  Real x, y;
581  bool leaving = m_type == SPxSolver::LEAVE;
582 
583  const Real* up = upBound.get_const_ptr();
584  const Real* low = lowBound.get_const_ptr();
585  const Real* vec = update.get_const_ptr();
586  const Real* upd = update.delta().values();
587  const int* idx = update.delta().indexMem();
588  const int* last = idx + update.delta().size();
589 
590  int nr = -1;
591  int bestNr = -1;
592 
593  for (idx += start; idx < last; idx += incr)
594  {
595  i = *idx;
596  x = upd[i];
597 
598  // in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables
599  if( leaving && ((iscoid && thesolver->isCoBasic(i)) || (!iscoid && thesolver->isBasic(i))) )
600  continue;
601 
602  if (x > stab)
603  {
604  y = (up[i] - vec[i]) / x;
605  if (y <= max)
606  {
607  val = y;
608  nr = i;
609  stab = x;
610  }
611  else if (y > best)
612  {
613  best = y;
614  bestNr = i;
615  }
616  }
617  else if (x < -stab)
618  {
619  y = (low[i] - vec[i]) / x;
620  if (y <= max)
621  {
622  val = y;
623  nr = i;
624  stab = -x;
625  }
626  else if (y > best)
627  {
628  best = y;
629  bestNr = i;
630  }
631  }
632  }
633 
634  if (nr < 0 && bestNr > 0)
635  {
636  if (upd[bestNr] > 0)
637  bestDelta = up[bestNr] - vec[bestNr];
638  else
639  bestDelta = vec[bestNr] - low[bestNr];
640  }
641 
642  return nr;
643 }
644 
645 
647  Real& val,
648  Real& stab,
649  Real& bestDelta,
650  Real max)
651 {
652  Real best = -infinity;
653  bestDelta = 0.0;
654  assert(m_type == SPxSolver::ENTER);
655  return maxSelect(val, stab, best, bestDelta, max,
656  thesolver->fVec(), thesolver->lbBound(), thesolver->ubBound(), 0, 1);
657 }
658 
660  int& nr,
661  Real& val,
662  Real& stab,
663  Real& bestDelta,
664  Real max
665 )
666 {
667  int indp, indc;
668  Real best = -infinity;
669  bestDelta = 0.0;
670  iscoid = true;
671  indc = maxSelect(val, stab, best, bestDelta, max,
673  iscoid = false;
674  indp = maxSelect(val, stab, best, bestDelta, max,
675  thesolver->pVec(), thesolver->lpBound(), thesolver->upBound(), 0, 1);
676 
677  if (indp >= 0)
678  {
679  nr = indp;
680  return thesolver->id(indp);
681  }
682  if (indc >= 0)
683  {
684  nr = indc;
685  return thesolver->coId(indc);
686  }
687  nr = -1;
688  return SPxId();
689 }
690 
692  Real& val,
693  Real& stab,
694  Real& bestDelta,
695  Real max)
696 {
697  Real best = infinity;
698  bestDelta = 0.0;
699  assert(m_type == SPxSolver::ENTER);
700  return minSelect(val, stab, best, bestDelta, max,
701  thesolver->fVec(), thesolver->lbBound(), thesolver->ubBound(), 0, 1);
702 }
703 
705  int& nr,
706  Real& val,
707  Real& stab,
708  Real& bestDelta,
709  Real max)
710 {
711  Real best = infinity;
712  bestDelta = 0.0;
713  iscoid = true;
714  int indc = minSelect(val, stab, best, bestDelta, max,
716  iscoid = false;
717  int indp = minSelect(val, stab, best, bestDelta, max,
718  thesolver->pVec(), thesolver->lpBound(), thesolver->upBound(), 0, 1);
719 
720  if (indp >= 0)
721  {
722  nr = indp;
723  return thesolver->id(indp);
724  }
725  if (indc >= 0)
726  {
727  nr = indc;
728  return thesolver->coId(indc);
729  }
730  nr = -1;
731  return SPxId();
732 }
733 
734 
735 bool SPxFastRT::maxShortLeave(Real& sel, int leave, Real maxabs)
736 {
737  assert(leave >= 0);
738  assert(maxabs >= 0);
739 
740  sel = thesolver->fVec().delta()[leave];
741 
742  if (sel > maxabs*SHORT)
743  {
744  sel = (thesolver->ubBound()[leave] - thesolver->fVec()[leave]) / sel;
745  return true;
746  }
747 
748  if (sel < -maxabs*SHORT)
749  {
750  sel = (thesolver->lbBound()[leave] - thesolver->fVec()[leave]) / sel;
751  return true;
752  }
753 
754  return false;
755 }
756 
757 bool SPxFastRT::minShortLeave(Real& sel, int leave, Real maxabs)
758 {
759  assert(leave >= 0);
760  assert(maxabs >= 0);
761 
762  sel = thesolver->fVec().delta()[leave];
763 
764  if (sel > maxabs*SHORT)
765  {
766  sel = (thesolver->lbBound()[leave] - thesolver->fVec()[leave]) / sel;
767  return true;
768  }
769 
770  if ( sel < -maxabs*SHORT)
771  {
772  sel = (thesolver->ubBound()[leave] - thesolver->fVec()[leave]) / sel;
773  return true;
774  }
775 
776  return false;
777 }
778 
779 bool SPxFastRT::maxReLeave(Real& sel, int leave, Real maxabs)
780 {
781  UpdateVector& vec = thesolver->fVec();
782  Vector& low = thesolver->lbBound();
783  Vector& up = thesolver->ubBound();
784 
785  if (leave < 0)
786  return true;
787 
788  if (up[leave] > low[leave])
789  {
790  Real x = vec.delta()[leave];
791 
792  if (sel < -fastDelta / maxabs)
793  {
794  sel = 0.0;
796  {
797  if (x < 0.0)
798  thesolver->shiftLBbound(leave, vec[leave]);
799  else
800  thesolver->shiftUBbound(leave, vec[leave]);
801  }
802  }
803  }
804  else
805  {
806  sel = 0.0;
807  thesolver->shiftLBbound(leave, vec[leave]);
808  thesolver->shiftUBbound(leave, vec[leave]);
809  }
810 
811  return false;
812 }
813 
814 bool SPxFastRT::minReLeave(Real& sel, int leave, Real maxabs)
815 {
816  UpdateVector& vec = thesolver->fVec();
817  Vector& low = thesolver->lbBound();
818  Vector& up = thesolver->ubBound();
819 
820  if (leave < 0)
821  return true;
822 
823  if (up[leave] > low[leave])
824  {
825  Real x = vec.delta()[leave];
826 
827  if (sel > fastDelta / maxabs)
828  {
829  sel = 0.0;
831  {
832  if (x > 0.0)
833  thesolver->shiftLBbound(leave, vec[leave]);
834  else
835  thesolver->shiftUBbound(leave, vec[leave]);
836  }
837  }
838  }
839  else
840  {
841  sel = 0.0;
842  thesolver->shiftLBbound(leave, vec[leave]);
843  thesolver->shiftUBbound(leave, vec[leave]);
844  }
845 
846  return false;
847 }
848 
850 {
851  Real maxabs, max, sel;
852  int leave = -1;
853  int cnt = 0;
854 
855  assert( m_type == SPxSolver::ENTER );
856 
857  // force instable pivot iff true (see explanation in enter.cpp and spxsolve.cpp)
858  bool instable = solver()->instableEnter;
859  Real lowstab = LOWSTAB;
860  assert(!instable || solver()->instableEnterId.isValid());
861 
862  resetTols();
863 
864  if (val > epsilon)
865  {
866  do
867  {
868  // phase 1:
869  max = val;
870  maxabs = 0.0;
871  leave = maxDelta(max, maxabs);
872  if (max == val)
873  return -1;
874 
875  if (!maxShortLeave(sel, leave, maxabs))
876  {
877  // phase 2:
878  Real stab, bestDelta;
879 
880  stab = 100.0 * minStability(maxabs);
881 
882  // force instable pivot iff instable is true (see explanation in enter.cpp and spxsolve.cpp)
883  if (instable)
884  leave = maxSelect(sel, lowstab, bestDelta, max);
885  else
886  leave = maxSelect(sel, stab, bestDelta, max);
887 
888  if (bestDelta < DELTA_SHIFT*TRIES)
889  cnt++;
890  else
891  cnt += TRIES;
892  }
893  if (!maxReLeave(sel, leave, maxabs))
894  break;
895  relax();
896  }
897  while (cnt < TRIES);
898  }
899  else if (val < -epsilon)
900  {
901  do
902  {
903  max = val;
904  maxabs = 0;
905  leave = minDelta(max, maxabs);
906 
907  assert(leave < 0 || !(thesolver->baseId(leave).isSPxColId()) || thesolver->desc().colStatus(thesolver->number(SPxColId(thesolver->baseId(leave)))) != SPxBasis::Desc::P_FIXED);
908 
909  if (max == val)
910  return -1;
911 
912  if (!minShortLeave(sel, leave, maxabs))
913  {
914  // phase 2:
915  Real stab, bestDelta;
916 
917  stab = 100.0 * minStability(maxabs);
918 
919  // force instable pivot iff instable is true (see explanation in enter.cpp and spxsolve.cpp)
920  if (instable)
921  leave = minSelect(sel, lowstab, bestDelta, max);
922  else
923  leave = minSelect(sel, stab, bestDelta, max);
924 
925  assert(leave < 0 || !(thesolver->baseId(leave).isSPxColId()) || thesolver->desc().colStatus(thesolver->number(SPxColId(thesolver->baseId(leave)))) != SPxBasis::Desc::P_FIXED);
926 
927  if (bestDelta < DELTA_SHIFT*TRIES)
928  cnt++;
929  else
930  cnt += TRIES;
931  }
932  if (!minReLeave(sel, leave, maxabs))
933  break;
934  relax();
935  }
936  while (cnt < TRIES);
937  }
938  else
939  return -1;
940 
941  MSG_DEBUG(
942  if (leave >= 0)
943  std::cout
944  << "DFSTRT01 "
945  << thesolver->basis().iteration() << "("
946  << std::setprecision(6) << thesolver->value() << ","
947  << std::setprecision(2) << thesolver->basis().stability() << "):"
948  << leave << "\t"
949  << std::setprecision(4) << sel << " "
950  << std::setprecision(4) << thesolver->fVec().delta()[leave] << " "
951  << std::setprecision(6) << maxabs
952  << std::endl;
953  else
954  std::cout << "DFSTRT02 " << thesolver->basis().iteration()
955  << ": skipping instable pivot" << std::endl;
956  )
957 
958  if (leave >= 0 || minStab > 2*solver()->epsilon())
959  {
960  val = sel;
961  if (leave >= 0)
962  tighten();
963  }
964 
965  assert(leave < 0 || !(thesolver->baseId(leave).isSPxColId()) || thesolver->desc().colStatus(thesolver->number(SPxColId(thesolver->baseId(leave)))) != SPxBasis::Desc::P_FIXED);
966 
967  return leave;
968 }
969 
970 
972  Real& sel,
973  Real maxabs,
974  const SPxId& id,
975  int nr)
976 {
977  Real x, d;
978  Vector* up;
979  Vector* low;
980 
981  UpdateVector& pvec = thesolver->pVec();
982  SSVector& pupd = thesolver->pVec().delta();
983  Vector& upb = thesolver->upBound();
984  Vector& lpb = thesolver->lpBound();
985  UpdateVector& cvec = thesolver->coPvec();
986  SSVector& cupd = thesolver->coPvec().delta();
987  Vector& ucb = thesolver->ucBound();
988  Vector& lcb = thesolver->lcBound();
989 
990  if (thesolver->isCoId(id))
991  {
992  if (thesolver->isCoBasic(nr))
993  {
994  cupd.clearIdx(nr);
995  return true;
996  }
997 
998  x = cvec[nr];
999  d = cupd[nr];
1000  up = &ucb;
1001  low = &lcb;
1002 
1003  if (d < 0.0)
1004  sel = (lcb[nr] - cvec[nr]) / d;
1005  else
1006  sel = (ucb[nr] - cvec[nr]) / d;
1007  }
1008  else if (thesolver->isId(id))
1009  {
1010  pvec[nr] = thesolver->vector(nr) * cvec;
1011  if (thesolver->isBasic(nr))
1012  {
1013  pupd.clearIdx(nr);
1014  return true;
1015  }
1016 
1017  x = pvec[nr];
1018  d = pupd[nr];
1019  up = &upb;
1020  low = &lpb;
1021 
1022  if (d < 0.0)
1023  sel = (lpb[nr] - pvec[nr]) / d;
1024  else
1025  sel = (upb[nr] - pvec[nr]) / d;
1026  }
1027  else
1028  return true;
1029 
1030  if ((*up)[nr] != (*low)[nr])
1031  {
1032  if (sel < -fastDelta / maxabs)
1033  {
1034  if (d > 0.0)
1035  {
1036  thesolver->theShift -= (*up)[nr];
1037  sel = 0.0;
1038  (*up)[nr] = x + sel * d;
1039  thesolver->theShift += (*up)[nr];
1040  }
1041  else
1042  {
1043  thesolver->theShift += (*low)[nr];
1044  sel = 0.0;
1045  (*low)[nr] = x + sel * d;
1046  thesolver->theShift -= (*low)[nr];
1047  }
1048  }
1049  }
1050  else
1051  {
1052  sel = 0.0;
1053  if (x > (*up)[nr])
1054  thesolver->theShift += x - (*up)[nr];
1055  else
1056  thesolver->theShift += (*low)[nr] - x;
1057  (*up)[nr] = (*low)[nr] = x;
1058  }
1059 
1060  return false;
1061 }
1062 
1064  Real& sel,
1065  Real maxabs,
1066  const SPxId& id,
1067  int nr)
1068 {
1069  Real x, d;
1070  Vector* up;
1071  Vector* low;
1072 
1073  UpdateVector& pvec = thesolver->pVec();
1074  SSVector& pupd = thesolver->pVec().delta();
1075  Vector& upb = thesolver->upBound();
1076  Vector& lpb = thesolver->lpBound();
1077  UpdateVector& cvec = thesolver->coPvec();
1078  SSVector& cupd = thesolver->coPvec().delta();
1079  Vector& ucb = thesolver->ucBound();
1080  Vector& lcb = thesolver->lcBound();
1081 
1082  if (thesolver->isCoId(id))
1083  {
1084  if (thesolver->isCoBasic(nr))
1085  {
1086  cupd.clearIdx(nr);
1087  return true;
1088  }
1089  x = cvec[nr];
1090  d = cupd[nr];
1091  up = &ucb;
1092  low = &lcb;
1093  if (d > 0.0)
1094  sel = (thesolver->lcBound()[nr] - cvec[nr]) / d;
1095  else
1096  sel = (thesolver->ucBound()[nr] - cvec[nr]) / d;
1097  }
1098 
1099  else if (thesolver->isId(id))
1100  {
1101  pvec[nr] = thesolver->vector(nr) * cvec;
1102  if (thesolver->isBasic(nr))
1103  {
1104  pupd.clearIdx(nr);
1105  return true;
1106  }
1107  x = pvec[nr];
1108  d = pupd[nr];
1109  up = &upb;
1110  low = &lpb;
1111  if (d > 0.0)
1112  sel = (thesolver->lpBound()[nr] - pvec[nr]) / d;
1113  else
1114  sel = (thesolver->upBound()[nr] - pvec[nr]) / d;
1115  }
1116 
1117  else
1118  return true;
1119 
1120  if ((*up)[nr] != (*low)[nr])
1121  {
1122  if (sel > fastDelta / maxabs)
1123  {
1124  if (d < 0.0)
1125  {
1126  thesolver->theShift -= (*up)[nr];
1127  sel = 0.0;
1128  (*up)[nr] = x + sel * d;
1129  thesolver->theShift += (*up)[nr];
1130  }
1131  else
1132  {
1133  thesolver->theShift += (*low)[nr];
1134  sel = 0.0;
1135  (*low)[nr] = x + sel * d;
1136  thesolver->theShift -= (*low)[nr];
1137  }
1138  }
1139  }
1140  else
1141  {
1142  sel = 0.0;
1143  if (x > (*up)[nr])
1144  thesolver->theShift += x - (*up)[nr];
1145  else
1146  thesolver->theShift += (*low)[nr] - x;
1147  (*up)[nr] = (*low)[nr] = x;
1148  }
1149 
1150  return false;
1151 }
1152 
1154  const SPxId& enterId,
1155  int nr,
1156  Real max,
1157  Real maxabs) const
1158 {
1159  if (thesolver->isCoId(enterId))
1160  {
1161  if (max != 0.0)
1162  {
1163  Real x = thesolver->coPvec().delta()[nr];
1164  if (x < maxabs * SHORT && -x < maxabs * SHORT)
1165  return false;
1166  }
1167  return true;
1168  }
1169  else if (thesolver->isId(enterId))
1170  {
1171  if (max != 0.0)
1172  {
1173  Real x = thesolver->pVec().delta()[nr];
1174  if (x < maxabs * SHORT && -x < maxabs * SHORT)
1175  return false;
1176  }
1177  return true;
1178  }
1179 
1180  return false;
1181 }
1182 
1184 {
1185  SPxId enterId;
1186  Real max, sel;
1187  Real maxabs = 0.0;
1188  int nr;
1189  int cnt = 0;
1190 
1191  assert( m_type == SPxSolver::LEAVE );
1192 
1193  // force instable pivot iff true (see explanation in leave.cpp and spxsolve.cpp)
1194  bool instable = solver()->instableLeave;
1195  Real lowstab = LOWSTAB;
1196  assert(!instable || solver()->instableLeaveNum >= 0);
1197 
1198  resetTols();
1199  sel = 0.0;
1200 
1201  if (val > epsilon)
1202  {
1203  do
1204  {
1205  maxabs = 0.0;
1206  max = val;
1207 
1208  enterId = maxDelta(nr, max, maxabs);
1209  if (!enterId.isValid())
1210  return enterId;
1211  assert(max >= 0.0);
1212  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1213 
1214  if (!shortEnter(enterId, nr, max, maxabs))
1215  {
1216  Real bestDelta, stab;
1217 
1218  stab = minStability(maxabs);
1219 
1220  // force instable pivot iff instable is true (see explanation in leave.cpp and spxsolve.cpp)
1221  if (instable)
1222  {
1223  enterId = maxSelect(nr, sel, lowstab, bestDelta, max);
1224  }
1225  else
1226  {
1227  enterId = maxSelect(nr, sel, stab, bestDelta, max);
1228  }
1229  if (bestDelta < DELTA_SHIFT*TRIES)
1230  cnt++;
1231  else
1232  cnt += TRIES;
1233  }
1234  if (!maxReEnter(sel, maxabs, enterId, nr))
1235  break;
1236  relax();
1237  }
1238  while (cnt < TRIES);
1239  }
1240  else if (val < -epsilon)
1241  {
1242  do
1243  {
1244  maxabs = 0.0;
1245  max = val;
1246  enterId = minDelta(nr, max, maxabs);
1247  if (!enterId.isValid())
1248  return enterId;
1249  assert(max <= 0.0);
1250  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1251 
1252  if (!shortEnter(enterId, nr, max, maxabs))
1253  {
1254  Real bestDelta, stab;
1255 
1256  stab = minStability(maxabs);
1257 
1258  // force instable pivot iff instable is true (see explanation in leave.cpp and spxsolve.cpp)
1259  if (instable)
1260  {
1261  enterId = minSelect(nr, sel, lowstab, bestDelta, max);
1262  }
1263  else
1264  {
1265  enterId = minSelect(nr, sel, stab, bestDelta, max);
1266  }
1267  if (bestDelta < DELTA_SHIFT*TRIES)
1268  cnt++;
1269  else
1270  cnt += TRIES;
1271  }
1272  if (!minReEnter(sel, maxabs, enterId, nr))
1273  break;
1274  relax();
1275  }
1276  while (cnt < TRIES);
1277  }
1278 
1279  MSG_DEBUG(
1280  if (enterId.isValid())
1281  {
1282  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1283 
1284  Real x;
1285  if (thesolver->isCoId(enterId))
1286  x = thesolver->coPvec().delta()[ thesolver->number(enterId) ];
1287  else
1288  x = thesolver->pVec().delta()[ thesolver->number(enterId) ];
1289  std::cout << "DFSTRT03 " << thesolver->basis().iteration() << ": "
1290  << sel << '\t' << x << " (" << maxabs << ")" << std::endl;
1291  }
1292  else
1293  std::cout << "DFSTRT04 " << thesolver->basis().iteration()
1294  << ": skipping instable pivot" << std::endl;
1295  )
1296 
1297 
1298  if (enterId.isValid() || minStab > 2*epsilon)
1299  {
1300  val = sel;
1301  if (enterId.isValid())
1302  tighten();
1303  }
1304 
1305  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1306 
1307  return enterId;
1308 }
1309 
1311 {
1312  thesolver = spx;
1313  setType(spx->type());
1314 }
1315 
1317 {
1318  m_type = type;
1319 
1320  minStab = MINSTAB;
1321  fastDelta = delta;
1322 }
1323 } // namespace soplex
Fast shifting ratio test.
bool maxReEnter(Real &sel, Real maxabs, const SPxId &id, int nr)
Definition: spxfastrt.cpp:971
const R * values() const
Returns array values.
Definition: ssvectorbase.h:288
primal variable is fixed to both bounds
Definition: spxbasis.h:190
Desc::Status dualStatus(const SPxColId &id) const
dual Status for the column variable with ID id of the loaded LP.
Definition: spxbasis.cpp:34
Type
Algorithmic type.
Definition: spxsolver.h:124
bool maxShortLeave(Real &sel, int leave, Real maxabs)
Definition: spxfastrt.cpp:735
bool isValid() const
returns TRUE iff the id is a valid column or row identifier.
Definition: spxid.h:150
int iteration() const
returns number of basis changes since last load().
Definition: spxbasis.h:539
bool isSPxColId() const
is id a column id?
Definition: spxid.h:165
#define TRIES
Definition: spxfastrt.cpp:43
Real delta
allowed bound violation
const Vector & lbBound() const
lower bound for fVec.
Definition: spxsolver.h:1220
int number(const SPxRowId &id) const
Returns the row number of the row with identifier id.
Definition: spxlpbase.h:450
Real fastDelta
currently allowed infeasibility.
Definition: spxfastrt.h:52
#define SHORT
Definition: spxfastrt.cpp:44
const R * get_const_ptr() const
Conversion to C-style pointer.
Definition: vectorbase.h:412
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1184
void shiftLBbound(int i, Real to)
shift i &#39;th lbBound to to.
Definition: spxsolver.h:1444
Real epsilon
|value| < epsilon is considered 0.
Definition: spxfastrt.h:50
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1339
const Vector & ubBound() const
upper bound for fVec.
Definition: spxsolver.h:1202
virtual void setType(SPxSolver::Type type)
Definition: spxfastrt.cpp:1316
bool isCoId(const SPxId &p_id) const
Is p_id a CoId.
Definition: spxsolver.h:1005
Ids for LP columns.Class SPxColId provides DataKeys for the column indices of an SPxLP.
Definition: spxid.h:36
SPxId coId(int i) const
id of i &#39;th covector.
Definition: spxsolver.h:978
void relax()
relaxes stability requirements.
Definition: spxfastrt.cpp:80
bool maxReLeave(Real &sel, int leave, Real maxabs)
Definition: spxfastrt.cpp:779
int maxDelta(Real &val, Real &maxabs, UpdateVector &update, const Vector &lowBound, const Vector &upBound, int start, int incr) const
Max phase 1 value.
Definition: spxfastrt.cpp:101
#define LOWSTAB
Definition: spxfastrt.cpp:42
virtual Real value()
current objective value.
Definition: spxsolver.cpp:863
int * altIndexMem()
Returns array indices.
Definition: ssvectorbase.h:300
bool isId(const SPxId &p_id) const
Is p_id an SPxId ?
Definition: spxsolver.h:996
virtual int selectLeave(Real &val, Real)
Definition: spxfastrt.cpp:849
Entering Simplex.
Definition: spxsolver.h:134
Real minStability(Real maxabs)
Compute stability requirement.
Definition: spxfastrt.cpp:87
R * altValues()
Returns array values.
Definition: ssvectorbase.h:307
Generic Ids for LP rows or columns.Both SPxColIds and SPxRowIds may be treated uniformly as SPxIds: ...
Definition: spxid.h:85
void resetTols()
resets tolerances (epsilon).
Definition: spxfastrt.cpp:48
int minSelect(Real &val, Real &stab, Real &best, Real &bestDelta, Real max, const UpdateVector &upd, const Vector &low, const Vector &up, int start=0, int incr=1) const
selects stable index for minimizing ratio test.
Definition: spxfastrt.cpp:488
Leaving Simplex.
Definition: spxsolver.h:143
UpdateVector & coPvec() const
copricing vector.
Definition: spxsolver.h:1259
double Real
SOPLEX_DEBUG.
Definition: spxdefines.h:200
bool minReLeave(Real &sel, int leave, Real maxabs)
numerical stability tests.
Definition: spxfastrt.cpp:814
#define MSG_DEBUG(x)
Definition: spxdefines.h:127
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1616
bool isCoBasic(int i) const
is the i &#39;th covector basic ?
Definition: spxsolver.h:1169
Dense vector with semi-sparse vector for updatesIn many algorithms vectors are updated in every itera...
Definition: updatevector.h:53
int dim() const
Dimension of vector.
Definition: vectorbase.h:174
const Vector & lcBound() const
Definition: spxsolver.h:1299
Type type() const
return current Type.
Definition: spxsolver.h:412
int maxSelect(Real &val, Real &stab, Real &best, Real &bestDelta, Real max, const UpdateVector &upd, const Vector &low, const Vector &up, int start=0, int incr=1) const
selects stable index for maximizing ratio test.
Definition: spxfastrt.cpp:567
void shiftUBbound(int i, Real to)
shift i &#39;th ubBound to to.
Definition: spxsolver.h:1437
Status & colStatus(int i)
Definition: spxbasis.h:254
SPxId & baseId(int i)
Definition: spxbasis.h:497
const Vector & upBound() const
Definition: spxsolver.h:1344
Debugging, floating point type and parameter definitions.
bool isSetup() const
Returns setup status.
Definition: ssvectorbase.h:120
void setSize(int n)
Sets number of nonzeros (thereby unSetup SSVectorBase).
Definition: ssvectorbase.h:553
void clearIdx(int i)
Clears element i.
Definition: ssvectorbase.h:242
Sequential object-oriented SimPlex.SPxSolver is an LP solver class using the revised Simplex algorith...
Definition: spxsolver.h:84
SPxSolver * thesolver
the solver
Everything should be within this namespace.
void tighten()
tightens stability requirements.
Definition: spxfastrt.cpp:58
bool iscoid
flag used in methods minSelect/maxSelect to retrieve correct basis status
Definition: spxfastrt.h:54
const SVector & vector(int i) const
i &#39;th vector.
Definition: spxsolver.h:1018
bool minShortLeave(Real &sel, int leave, Real maxabs)
tests for stop after phase 1.
Definition: spxfastrt.cpp:757
int minDelta(Real &val, Real &maxabs, UpdateVector &update, const Vector &lowBound, const Vector &upBound, int start, int incr) const
Min phase 1 value.
Definition: spxfastrt.cpp:256
virtual void load(SPxSolver *solver)
Definition: spxfastrt.cpp:1310
Real stability() const
returns the stability of the basis matrix.
Definition: spxbasis.h:600
SPxId id(int i) const
id of i &#39;th vector.
Definition: spxsolver.h:959
const Vector & lpBound() const
Definition: spxsolver.h:1365
void forceSetup()
Forces setup status.
Definition: ssvectorbase.h:162
Real epsilon() const
values are considered to be 0.
Definition: spxsolver.h:670
Real theShift
sum of all shifts applied to any bound.
Definition: spxsolver.h:242
const Real infinity
Definition: spxdefines.cpp:26
virtual SPxId selectEnter(Real &val, int)
Definition: spxfastrt.cpp:1183
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1124
bool shortEnter(const SPxId &enterId, int nr, Real max, Real maxabs) const
Tests and returns whether a shortcut after phase 1 is feasible for the selected enter pivot...
Definition: spxfastrt.cpp:1153
const int * indexMem() const
Returns array indices.
Definition: ssvectorbase.h:282
Real minStab
parameter for computing minimum stability requirement
Definition: spxfastrt.h:48
dual variable has two bounds
Definition: spxbasis.h:194
const Desc & desc() const
Definition: spxbasis.h:457
SSVector & delta()
update vector , writeable
Definition: updatevector.h:122
#define MINSTAB
Definition: spxfastrt.cpp:41
const Vector & ucBound() const
Definition: spxsolver.h:1278
bool minReEnter(Real &sel, Real maxabs, const SPxId &id, int nr)
numerical stability check.
Definition: spxfastrt.cpp:1063
#define EPSILON
Definition: spxfastrt.cpp:46
SPxSolver::Type m_type
internal storage of type
#define DELTA_SHIFT
Definition: spxfastrt.cpp:45
int size() const
Returns the number of nonzeros.
Definition: ssvectorbase.h:199
virtual SPxSolver * solver() const
returns loaded LP solver.