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-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 <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, bool polish)
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;
795  if( !polish && thesolver->dualStatus(thesolver->baseId(leave)) != SPxBasis::Desc::D_ON_BOTH )
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  if( !polish )
808  {
809  thesolver->shiftLBbound(leave, vec[leave]);
810  thesolver->shiftUBbound(leave, vec[leave]);
811  }
812  }
813 
814  return false;
815 }
816 
817 bool SPxFastRT::minReLeave(Real& sel, int leave, Real maxabs, bool polish)
818 {
819  UpdateVector& vec = thesolver->fVec();
820  Vector& low = thesolver->lbBound();
821  Vector& up = thesolver->ubBound();
822 
823  if (leave < 0)
824  return true;
825 
826  if (up[leave] > low[leave])
827  {
828  Real x = vec.delta()[leave];
829 
830  if (sel > fastDelta / maxabs)
831  {
832  sel = 0.0;
833  if( !polish && thesolver->dualStatus(thesolver->baseId(leave)) != SPxBasis::Desc::D_ON_BOTH )
834  {
835  if (x > 0.0)
836  thesolver->shiftLBbound(leave, vec[leave]);
837  else
838  thesolver->shiftUBbound(leave, vec[leave]);
839  }
840  }
841  }
842  else
843  {
844  sel = 0.0;
845  if( !polish )
846  {
847  thesolver->shiftLBbound(leave, vec[leave]);
848  thesolver->shiftUBbound(leave, vec[leave]);
849  }
850  }
851 
852  return false;
853 }
854 
855 int SPxFastRT::selectLeave(Real& val, Real, bool polish)
856 {
857  Real maxabs, max, sel;
858  int leave = -1;
859  int cnt = 0;
860 
861  assert( m_type == SPxSolver::ENTER );
862 
863  // force instable pivot iff true (see explanation in enter.cpp and spxsolve.cpp)
864  bool instable = solver()->instableEnter;
865  Real lowstab = LOWSTAB;
866  assert(!instable || solver()->instableEnterId.isValid());
867 
868  resetTols();
869 
870  if (val > epsilon)
871  {
872  do
873  {
874  // phase 1:
875  max = val;
876  maxabs = 0.0;
877  leave = maxDelta(max, maxabs);
878  if (max == val)
879  return -1;
880 
881  if (!maxShortLeave(sel, leave, maxabs))
882  {
883  // phase 2:
884  Real stab, bestDelta;
885 
886  stab = 100.0 * minStability(maxabs);
887 
888  // force instable pivot iff instable is true (see explanation in enter.cpp and spxsolve.cpp)
889  if (instable)
890  leave = maxSelect(sel, lowstab, bestDelta, max);
891  else
892  leave = maxSelect(sel, stab, bestDelta, max);
893 
894  if (bestDelta < DELTA_SHIFT*TRIES)
895  cnt++;
896  else
897  cnt += TRIES;
898  }
899  if (!maxReLeave(sel, leave, maxabs, polish))
900  break;
901  relax();
902  }
903  while (cnt < TRIES);
904  }
905  else if (val < -epsilon)
906  {
907  do
908  {
909  max = val;
910  maxabs = 0;
911  leave = minDelta(max, maxabs);
912 
913  assert(leave < 0 || !(thesolver->baseId(leave).isSPxColId()) || thesolver->desc().colStatus(thesolver->number(SPxColId(thesolver->baseId(leave)))) != SPxBasis::Desc::P_FIXED);
914 
915  if (max == val)
916  return -1;
917 
918  if (!minShortLeave(sel, leave, maxabs))
919  {
920  // phase 2:
921  Real stab, bestDelta;
922 
923  stab = 100.0 * minStability(maxabs);
924 
925  // force instable pivot iff instable is true (see explanation in enter.cpp and spxsolve.cpp)
926  if (instable)
927  leave = minSelect(sel, lowstab, bestDelta, max);
928  else
929  leave = minSelect(sel, stab, bestDelta, max);
930 
931  assert(leave < 0 || !(thesolver->baseId(leave).isSPxColId()) || thesolver->desc().colStatus(thesolver->number(SPxColId(thesolver->baseId(leave)))) != SPxBasis::Desc::P_FIXED);
932 
933  if (bestDelta < DELTA_SHIFT*TRIES)
934  cnt++;
935  else
936  cnt += TRIES;
937  }
938  if (!minReLeave(sel, leave, maxabs, polish))
939  break;
940  relax();
941  }
942  while (cnt < TRIES);
943  }
944  else
945  return -1;
946 
947  MSG_DEBUG(
948  if (leave >= 0)
949  std::cout
950  << "DFSTRT01 "
951  << thesolver->basis().iteration() << "("
952  << std::setprecision(6) << thesolver->value() << ","
953  << std::setprecision(2) << thesolver->basis().stability() << "):"
954  << leave << "\t"
955  << std::setprecision(4) << sel << " "
956  << std::setprecision(4) << thesolver->fVec().delta()[leave] << " "
957  << std::setprecision(6) << maxabs
958  << std::endl;
959  else
960  std::cout << "DFSTRT02 " << thesolver->basis().iteration()
961  << ": skipping instable pivot" << std::endl;
962  )
963 
964  if( polish && leave >= 0 )
965  {
966  assert( thesolver->rep() == SPxSolver::COLUMN );
967  SPxId leaveId = thesolver->baseId(leave);
968  // decide whether the chosen leave index contributes to the polishing objective
969  if( thesolver->polishObj == SPxSolver::SolutionPolish::MAXBASICSLACK )
970  {
971  // only allow (integer) variables to leave the basis
972  if( leaveId.isSPxRowId() )
973  return -1;
974  else if( thesolver->integerVariables.size() == thesolver->nCols() )
975  {
976  if( leaveId.isSPxColId() && thesolver->integerVariables[thesolver->number(leaveId)] == 0 )
977  return -1;
978  }
979  }
980  else if( thesolver->polishObj == SPxSolver::SolutionPolish::MINBASICSLACK )
981  {
982  // only allow slacks and continuous variables to leave the basis
984  {
985  if( thesolver->baseId(leave).isSPxColId() && thesolver->integerVariables[thesolver->number(leaveId)] == 1 )
986  return -1;
987  }
988  else if( thesolver->baseId(leave).isSPxColId() )
989  return -1;
990  }
991  }
992 
993  if (leave >= 0 || minStab > 2*solver()->epsilon())
994  {
995  val = sel;
996  if (leave >= 0)
997  tighten();
998  }
999 
1000  assert(leave < 0 || !(thesolver->baseId(leave).isSPxColId()) || thesolver->desc().colStatus(thesolver->number(SPxColId(thesolver->baseId(leave)))) != SPxBasis::Desc::P_FIXED);
1001 
1002  return leave;
1003 }
1004 
1005 
1007  Real& sel,
1008  Real maxabs,
1009  const SPxId& id,
1010  int nr)
1011 {
1012  Real x, d;
1013  Vector* up;
1014  Vector* low;
1015 
1016  UpdateVector& pvec = thesolver->pVec();
1017  SSVector& pupd = thesolver->pVec().delta();
1018  Vector& upb = thesolver->upBound();
1019  Vector& lpb = thesolver->lpBound();
1020  UpdateVector& cvec = thesolver->coPvec();
1021  SSVector& cupd = thesolver->coPvec().delta();
1022  Vector& ucb = thesolver->ucBound();
1023  Vector& lcb = thesolver->lcBound();
1024 
1025  if (thesolver->isCoId(id))
1026  {
1027  if (thesolver->isCoBasic(nr))
1028  {
1029  cupd.clearIdx(nr);
1030  return true;
1031  }
1032 
1033  x = cvec[nr];
1034  d = cupd[nr];
1035  up = &ucb;
1036  low = &lcb;
1037 
1038  if (d < 0.0)
1039  sel = (lcb[nr] - cvec[nr]) / d;
1040  else
1041  sel = (ucb[nr] - cvec[nr]) / d;
1042  }
1043  else if (thesolver->isId(id))
1044  {
1045  pvec[nr] = thesolver->vector(nr) * cvec;
1046  if (thesolver->isBasic(nr))
1047  {
1048  pupd.clearIdx(nr);
1049  return true;
1050  }
1051 
1052  x = pvec[nr];
1053  d = pupd[nr];
1054  up = &upb;
1055  low = &lpb;
1056 
1057  if (d < 0.0)
1058  sel = (lpb[nr] - pvec[nr]) / d;
1059  else
1060  sel = (upb[nr] - pvec[nr]) / d;
1061  }
1062  else
1063  return true;
1064 
1065  if ((*up)[nr] != (*low)[nr])
1066  {
1067  if (sel < -fastDelta / maxabs)
1068  {
1069  if (d > 0.0)
1070  {
1071  thesolver->theShift -= (*up)[nr];
1072  sel = 0.0;
1073  (*up)[nr] = x + sel * d;
1074  thesolver->theShift += (*up)[nr];
1075  }
1076  else
1077  {
1078  thesolver->theShift += (*low)[nr];
1079  sel = 0.0;
1080  (*low)[nr] = x + sel * d;
1081  thesolver->theShift -= (*low)[nr];
1082  }
1083  }
1084  }
1085  else
1086  {
1087  sel = 0.0;
1088  if (x > (*up)[nr])
1089  thesolver->theShift += x - (*up)[nr];
1090  else
1091  thesolver->theShift += (*low)[nr] - x;
1092  (*up)[nr] = (*low)[nr] = x;
1093  }
1094 
1095  return false;
1096 }
1097 
1099  Real& sel,
1100  Real maxabs,
1101  const SPxId& id,
1102  int nr)
1103 {
1104  Real x, d;
1105  Vector* up;
1106  Vector* low;
1107 
1108  UpdateVector& pvec = thesolver->pVec();
1109  SSVector& pupd = thesolver->pVec().delta();
1110  Vector& upb = thesolver->upBound();
1111  Vector& lpb = thesolver->lpBound();
1112  UpdateVector& cvec = thesolver->coPvec();
1113  SSVector& cupd = thesolver->coPvec().delta();
1114  Vector& ucb = thesolver->ucBound();
1115  Vector& lcb = thesolver->lcBound();
1116 
1117  if (thesolver->isCoId(id))
1118  {
1119  if (thesolver->isCoBasic(nr))
1120  {
1121  cupd.clearIdx(nr);
1122  return true;
1123  }
1124  x = cvec[nr];
1125  d = cupd[nr];
1126  up = &ucb;
1127  low = &lcb;
1128  if (d > 0.0)
1129  sel = (thesolver->lcBound()[nr] - cvec[nr]) / d;
1130  else
1131  sel = (thesolver->ucBound()[nr] - cvec[nr]) / d;
1132  }
1133 
1134  else if (thesolver->isId(id))
1135  {
1136  pvec[nr] = thesolver->vector(nr) * cvec;
1137  if (thesolver->isBasic(nr))
1138  {
1139  pupd.clearIdx(nr);
1140  return true;
1141  }
1142  x = pvec[nr];
1143  d = pupd[nr];
1144  up = &upb;
1145  low = &lpb;
1146  if (d > 0.0)
1147  sel = (thesolver->lpBound()[nr] - pvec[nr]) / d;
1148  else
1149  sel = (thesolver->upBound()[nr] - pvec[nr]) / d;
1150  }
1151 
1152  else
1153  return true;
1154 
1155  if ((*up)[nr] != (*low)[nr])
1156  {
1157  if (sel > fastDelta / maxabs)
1158  {
1159  if (d < 0.0)
1160  {
1161  thesolver->theShift -= (*up)[nr];
1162  sel = 0.0;
1163  (*up)[nr] = x + sel * d;
1164  thesolver->theShift += (*up)[nr];
1165  }
1166  else
1167  {
1168  thesolver->theShift += (*low)[nr];
1169  sel = 0.0;
1170  (*low)[nr] = x + sel * d;
1171  thesolver->theShift -= (*low)[nr];
1172  }
1173  }
1174  }
1175  else
1176  {
1177  sel = 0.0;
1178  if (x > (*up)[nr])
1179  thesolver->theShift += x - (*up)[nr];
1180  else
1181  thesolver->theShift += (*low)[nr] - x;
1182  (*up)[nr] = (*low)[nr] = x;
1183  }
1184 
1185  return false;
1186 }
1187 
1189  const SPxId& enterId,
1190  int nr,
1191  Real max,
1192  Real maxabs) const
1193 {
1194  if (thesolver->isCoId(enterId))
1195  {
1196  if (max != 0.0)
1197  {
1198  Real x = thesolver->coPvec().delta()[nr];
1199  if (x < maxabs * SHORT && -x < maxabs * SHORT)
1200  return false;
1201  }
1202  return true;
1203  }
1204  else if (thesolver->isId(enterId))
1205  {
1206  if (max != 0.0)
1207  {
1208  Real x = thesolver->pVec().delta()[nr];
1209  if (x < maxabs * SHORT && -x < maxabs * SHORT)
1210  return false;
1211  }
1212  return true;
1213  }
1214 
1215  return false;
1216 }
1217 
1218 SPxId SPxFastRT::selectEnter(Real& val, int, bool polish)
1219 {
1220  SPxId enterId;
1221  Real max, sel;
1222  Real maxabs = 0.0;
1223  int nr;
1224  int cnt = 0;
1225 
1226  assert( m_type == SPxSolver::LEAVE );
1227 
1228  // force instable pivot iff true (see explanation in leave.cpp and spxsolve.cpp)
1229  bool instable = solver()->instableLeave;
1230  Real lowstab = LOWSTAB;
1231  assert(!instable || solver()->instableLeaveNum >= 0);
1232 
1233  resetTols();
1234  sel = 0.0;
1235 
1236  if (val > epsilon)
1237  {
1238  do
1239  {
1240  maxabs = 0.0;
1241  max = val;
1242 
1243  enterId = maxDelta(nr, max, maxabs);
1244  if (!enterId.isValid())
1245  return enterId;
1246 
1247  assert(max >= 0.0);
1248  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1249 
1250  if (!shortEnter(enterId, nr, max, maxabs))
1251  {
1252  Real bestDelta, stab;
1253 
1254  stab = minStability(maxabs);
1255 
1256  // force instable pivot iff instable is true (see explanation in leave.cpp and spxsolve.cpp)
1257  if (instable)
1258  {
1259  enterId = maxSelect(nr, sel, lowstab, bestDelta, max);
1260  }
1261  else
1262  {
1263  enterId = maxSelect(nr, sel, stab, bestDelta, max);
1264  }
1265  if (bestDelta < DELTA_SHIFT*TRIES)
1266  cnt++;
1267  else
1268  cnt += TRIES;
1269  }
1270  if (!maxReEnter(sel, maxabs, enterId, nr))
1271  break;
1272  relax();
1273  }
1274  while (cnt < TRIES);
1275  }
1276  else if (val < -epsilon)
1277  {
1278  do
1279  {
1280  maxabs = 0.0;
1281  max = val;
1282  enterId = minDelta(nr, max, maxabs);
1283  if (!enterId.isValid())
1284  return enterId;
1285 
1286  assert(max <= 0.0);
1287  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1288 
1289  if (!shortEnter(enterId, nr, max, maxabs))
1290  {
1291  Real bestDelta, stab;
1292 
1293  stab = minStability(maxabs);
1294 
1295  // force instable pivot iff instable is true (see explanation in leave.cpp and spxsolve.cpp)
1296  if (instable)
1297  {
1298  enterId = minSelect(nr, sel, lowstab, bestDelta, max);
1299  }
1300  else
1301  {
1302  enterId = minSelect(nr, sel, stab, bestDelta, max);
1303  }
1304  if (bestDelta < DELTA_SHIFT*TRIES)
1305  cnt++;
1306  else
1307  cnt += TRIES;
1308  }
1309  if (!minReEnter(sel, maxabs, enterId, nr))
1310  break;
1311  relax();
1312  }
1313  while (cnt < TRIES);
1314  }
1315 
1316  MSG_DEBUG(
1317  if (enterId.isValid())
1318  {
1319  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1320 
1321  Real x;
1322  if (thesolver->isCoId(enterId))
1323  x = thesolver->coPvec().delta()[ thesolver->number(enterId) ];
1324  else
1325  x = thesolver->pVec().delta()[ thesolver->number(enterId) ];
1326  std::cout << "DFSTRT03 " << thesolver->basis().iteration() << ": "
1327  << sel << '\t' << x << " (" << maxabs << ")" << std::endl;
1328  }
1329  else
1330  std::cout << "DFSTRT04 " << thesolver->basis().iteration()
1331  << ": skipping instable pivot" << std::endl;
1332  )
1333 
1334  if( polish && enterId.isValid() )
1335  {
1336  assert( thesolver->rep() == SPxSolver::ROW );
1337  // decide whether the chosen entering index contributes to the polishing objective
1338  if( thesolver->polishObj == SPxSolver::SolutionPolish::MAXBASICSLACK )
1339  {
1340  // only allow (integer) variables to enter the basis
1341  if( enterId.isSPxRowId() )
1342  return SPxId();
1344  return SPxId();
1345  }
1346  else if( thesolver->polishObj == SPxSolver::SolutionPolish::MINBASICSLACK )
1347  {
1348  // only allow slacks and continuous variables to enter the basis
1350  {
1351  if( enterId.isSPxColId() && thesolver->integerVariables[thesolver->number(enterId)] == 1 )
1352  return SPxId();
1353  }
1354  else if( enterId.isSPxColId() )
1355  return SPxId();
1356  }
1357  }
1358 
1359 
1360  if (enterId.isValid() || minStab > 2*epsilon)
1361  {
1362  val = sel;
1363  if (enterId.isValid())
1364  tighten();
1365  }
1366 
1367  assert(!enterId.isValid() || !solver()->isBasic(enterId));
1368 
1369  return enterId;
1370 }
1371 
1373 {
1374  thesolver = spx;
1375  setType(spx->type());
1376 }
1377 
1379 {
1380  m_type = type;
1381 
1382  minStab = MINSTAB;
1383  fastDelta = delta;
1384 }
1385 } // namespace soplex
Fast shifting ratio test.
SPxId coId(int i) const
id of i &#39;th covector.
Definition: spxsolver.h:1077
bool maxReEnter(Real &sel, Real maxabs, const SPxId &id, int nr)
Definition: spxfastrt.cpp:1006
const Vector & ucBound() const
Definition: spxsolver.h:1377
int iteration() const
returns number of basis changes since last load().
Definition: spxbasis.h:545
bool isSetup() const
Returns setup status.
Definition: ssvectorbase.h:120
primal variable is fixed to both bounds
Definition: spxbasis.h:190
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
Type
Algorithmic type.
Definition: spxsolver.h:124
bool maxShortLeave(Real &sel, int leave, Real maxabs)
Definition: spxfastrt.cpp:735
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
#define TRIES
Definition: spxfastrt.cpp:43
Real delta
allowed bound violation
Real fastDelta
currently allowed infeasibility.
Definition: spxfastrt.h:52
#define SHORT
Definition: spxfastrt.cpp:44
int number(const SPxRowId &id) const
Returns the row number of the row with identifier id.
Definition: spxlpbase.h:522
virtual int selectLeave(Real &val, Real, bool polish=false)
Definition: spxfastrt.cpp:855
bool isId(const SPxId &p_id) const
Is p_id an SPxId ?
Definition: spxsolver.h:1095
bool minReLeave(Real &sel, int leave, Real maxabs, bool polish=false)
numerical stability tests.
Definition: spxfastrt.cpp:817
const Vector & lcBound() const
Definition: spxsolver.h:1398
void shiftLBbound(int i, Real to)
shift i &#39;th lbBound to to.
Definition: spxsolver.h:1543
Real epsilon
|value| < epsilon is considered 0.
Definition: spxfastrt.h:50
virtual void setType(SPxSolver::Type type)
Definition: spxfastrt.cpp:1378
Ids for LP columns.Class SPxColId provides DataKeys for the column indices of an SPxLP.
Definition: spxid.h:36
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
void relax()
relaxes stability requirements.
Definition: spxfastrt.cpp:80
Desc::Status dualStatus(const SPxColId &id) const
dual Status for the column variable with ID id of the loaded LP.
Definition: spxbasis.cpp:34
#define LOWSTAB
Definition: spxfastrt.cpp:42
virtual Real value()
current objective value.
Definition: spxsolver.cpp:889
rowwise representation.
Definition: spxsolver.h:107
int * altIndexMem()
Returns array indices.
Definition: ssvectorbase.h:311
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:1301
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:318
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:1358
void resetTols()
resets tolerances (epsilon).
Definition: spxfastrt.cpp:48
Leaving Simplex.
Definition: spxsolver.h:143
double Real
Definition: spxdefines.h:214
const R * values() const
Returns array values.
Definition: ssvectorbase.h:299
#define MSG_DEBUG(x)
Definition: spxdefines.h:128
const Vector & lbBound() const
lower bound for fVec.
Definition: spxsolver.h:1319
SPxId id(int i) const
id of i &#39;th vector.
Definition: spxsolver.h:1058
UpdateVector & fVec() const
feasibility vector.
Definition: spxsolver.h:1283
bool isSPxColId() const
is id a column id?
Definition: spxid.h:165
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:1188
bool isBasic(SPxBasis::Desc::Status stat) const
does stat describe a basic index ?
Definition: spxsolver.h:1223
Dense vector with semi-sparse vector for updatesIn many algorithms vectors are updated in every itera...
Definition: updatevector.h:53
void shiftUBbound(int i, Real to)
shift i &#39;th ubBound to to.
Definition: spxsolver.h:1536
Status & colStatus(int i)
Definition: spxbasis.h:254
SPxId & baseId(int i)
Definition: spxbasis.h:503
const int * indexMem() const
Returns array indices.
Definition: ssvectorbase.h:293
Real epsilon() const
values are considered to be 0.
Definition: spxsolver.h:757
Debugging, floating point type and parameter definitions.
void setSize(int n)
Sets number of nonzeros (thereby unSetup SSVectorBase).
Definition: ssvectorbase.h:580
void clearIdx(int i)
Clears element i.
Definition: ssvectorbase.h:253
bool isCoId(const SPxId &p_id) const
Is p_id a CoId.
Definition: spxsolver.h:1104
Sequential object-oriented SimPlex.SPxSolver is an LP solver class using the revised Simplex algorith...
Definition: spxsolver.h:84
SolutionPolish polishObj
objective of solution polishing
Definition: spxsolver.h:245
UpdateVector & pVec() const
pricing vector.
Definition: spxsolver.h:1438
SPxSolver * thesolver
the solver
const Vector & lpBound() const
Definition: spxsolver.h:1464
int dim() const
Dimension of vector.
Definition: vectorbase.h:215
int size() const
Returns the number of nonzeros.
Definition: ssvectorbase.h:199
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
virtual SPxSolver * solver() const
returns loaded LP solver.
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
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
bool maxReLeave(Real &sel, int leave, Real maxabs, bool polish=false)
Definition: spxfastrt.cpp:779
virtual void load(SPxSolver *solver)
Definition: spxfastrt.cpp:1372
const Vector & upBound() const
Definition: spxsolver.h:1443
virtual SPxId selectEnter(Real &val, int, bool polish=false)
Definition: spxfastrt.cpp:1218
void forceSetup()
Forces setup status.
Definition: ssvectorbase.h:162
bool isSPxRowId() const
is id a row id?
Definition: spxid.h:160
bool isValid() const
returns TRUE iff the id is a valid column or row identifier.
Definition: spxid.h:150
int size() const
return nr. of elements.
Definition: dataarray.h:211
Type type() const
return current Type.
Definition: spxsolver.h:474
Real theShift
sum of all shifts applied to any bound.
Definition: spxsolver.h:266
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:157
bool isCoBasic(int i) const
is the i &#39;th covector basic ?
Definition: spxsolver.h:1268
DataArray< int > integerVariables
supplementary variable information, 0: continous variable, 1: integer variable
Definition: spxsolver.h:428
Real minStab
parameter for computing minimum stability requirement
Definition: spxfastrt.h:48
dual variable has two bounds
Definition: spxbasis.h:194
const SVector & vector(int i) const
i &#39;th vector.
Definition: spxsolver.h:1117
SSVector & delta()
update vector , writeable
Definition: updatevector.h:122
#define MINSTAB
Definition: spxfastrt.cpp:41
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1715
bool minReEnter(Real &sel, Real maxabs, const SPxId &id, int nr)
numerical stability check.
Definition: spxfastrt.cpp:1098
#define EPSILON
Definition: spxfastrt.cpp:46
Real stability() const
returns the stability of the basis matrix.
Definition: spxbasis.h:619
SPxSolver::Type m_type
internal storage of type
const Desc & desc() const
Definition: spxbasis.h:463
Representation rep() const
return the current basis representation.
Definition: spxsolver.h:468
columnwise representation.
Definition: spxsolver.h:108
#define DELTA_SHIFT
Definition: spxfastrt.cpp:45