1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2022 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 "soplex/spxdefines.h"
(1) Event include_recursion: |
#include file "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/soplex/src/soplex/spxfastrt.h" includes itself: spxfastrt.h -> spxfastrt.hpp -> spxfastrt.h |
(2) Event caretline: |
^ |
20 #include "soplex/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 SHORTVAL 1e-5
45 #define DELTA_SHIFT 1e-5
46 #define EPSILON 1e-10
47
48
49
50 template <class R>
51 void SPxFastRT<R>::resetTols()
52 {
53 // epsilon = thesolver->epsilon();
54 epsilon = EPSILON;
55 /*
56 if(thesolver->basis().stability() < 1e-4)
57 epsilon *= 1e-4 / thesolver->basis().stability();
58 */
59 }
60
61 template <class R>
62 void SPxFastRT<R>::tighten()
63 {
64 /*
65 if((delta > 1.99 * DELTA_SHIFT && thesolver->theShift < 1e-4) ||
66 (delta > 1e-4 && thesolver->theShift > 1e-4))
67 */
68 // if(delta > 1.99 * DELTA_SHIFT)
69 if(fastDelta >= this->delta + DELTA_SHIFT)
70 {
71 fastDelta -= DELTA_SHIFT;
72
73 if(fastDelta > 1e-4)
74 fastDelta -= 2 * DELTA_SHIFT;
75 }
76
77 if(minStab < MINSTAB)
78 {
79 minStab /= 0.90;
80
81 if(minStab < 1e-6)
82 minStab /= 0.90;
83 }
84 }
85
86 template <class R>
87 void SPxFastRT<R>::relax()
88 {
89 minStab *= 0.95;
90 fastDelta += 3 * DELTA_SHIFT;
91 // delta += 2 * (thesolver->theShift > delta) * DELTA_SHIFT;
92 }
93
94 template <class R>
95 R SPxFastRT<R>::minStability(R maxabs)
96 {
97 if(maxabs < 1000.0)
98 return minStab;
99
100 return maxabs * minStab / 1000.0;
101 }
102
103 /* The code below implements phase 1 of the ratio test. It differs from the description in the
104 * 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$.
105 *
106 * This change leads to the following behavior of the source code. Consider the first case (x >
107 * epsilon, u < infinity): If u - vec[i] <= 0, vec[i] violates the upper bound. In the Harris ratio
108 * test, we would compute (u - vec[i] + delta)/upd[i]. The code computes instead delta/upd[i].
109 */
110 template <class R>
111 int SPxFastRT<R>::maxDelta(
112 R& val, /* on return: maximum step length */
113 R& maxabs, /* on return: maximum absolute value in upd VectorBase<R> */
114 UpdateVector<R>& update,
115 const VectorBase<R>& lowBound,
116 const VectorBase<R>& upBound,
117 int start,
118 int incr) const
119 {
120 int i, sel;
121 R x, y, max;
122 R u, l;
123 bool leaving = this->m_type == SPxSolverBase<R>::LEAVE;
124 bool enterrowrep = !leaving && this->thesolver->theRep == SPxSolverBase<R>::ROW;
125
126 R mabs = maxabs;
127
128 const R* up = upBound.get_const_ptr();
129 const R* low = lowBound.get_const_ptr();
130 const R* vec = update.get_const_ptr();
131 const R* upd = update.delta().values();
132 const int* idx = update.delta().indexMem();
133
134 sel = -1;
135 max = val;
136
137 if(update.delta().isSetup())
138 {
139 const int* last = idx + update.delta().size();
140
141 for(idx += start; idx < last; idx += incr)
142 {
143 i = *idx;
144
145 /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
146 if(leaving && ((iscoid && this->thesolver->isCoBasic(i)) || (!iscoid
147 && this->thesolver->isBasic(i))))
148 continue;
149
150 if(enterrowrep && this->thesolver->baseId(i).isSPxColId()
151 && this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(i))))
152 == SPxBasisBase<R>::Desc::P_FIXED)
153 continue;
154
155 x = upd[i];
156
157 if(x > epsilon)
158 {
159 // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
160 mabs = (x > mabs) ? x : mabs;
161 u = up[i];
162
163 if(u < R(infinity))
164 {
165 y = u - vec[i];
166
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 else if(x < -epsilon)
180 {
181 // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
182 mabs = (-x > mabs) ? -x : mabs;
183 l = low[i];
184
185 if(l > R(-infinity))
186 {
187 y = l - vec[i];
188
189 if(y >= 0)
190 x = - fastDelta / x;
191 else
192 x = (y - fastDelta) / x;
193
194 if(x < max)
195 {
196 max = x;
197 sel = i;
198 }
199 }
200 }
201 }
202 }
203 else
204 {
205 /* In this case, the indices of the semi-sparse Vector update.delta() are not set up and are filled below. */
206 int* l_idx = update.delta().altIndexMem();
207 R* uval = update.delta().altValues();
208 const R* uend = uval + update.dim();
209 assert(uval == upd);
210
211 for(i = 0; uval < uend; ++uval, ++i)
212 {
213 x = *uval;
214
215 if(x != 0.0)
216 {
217 if(x >= -epsilon && x <= epsilon)
218 {
219 *uval = 0.0;
220 continue;
221 }
222 else
223 *l_idx++ = i;
224
225 /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
226 if(leaving && ((iscoid && this->thesolver->isCoBasic(i)) || (!iscoid
227 && this->thesolver->isBasic(i))))
228 continue;
229
230 if(enterrowrep && this->thesolver->baseId(i).isSPxColId()
231 && this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(i))))
232 == SPxBasisBase<R>::Desc::P_FIXED)
233 continue;
234
235 if(x > epsilon)
236 {
237 mabs = (x > mabs) ? x : mabs;
238 u = up[i];
239
240 if(u < R(infinity))
241 {
242 y = u - vec[i];
243
244 if(y <= 0)
245 x = fastDelta / x;
246 else
247 x = (y + fastDelta) / x;
248
249 if(x < max)
250 {
251 max = x;
252 sel = i;
253 }
254 }
255 }
256 else if(x < -epsilon)
257 {
258 mabs = (-x > mabs) ? -x : mabs;
259 l = low[i];
260
261 if(l > R(-infinity))
262 {
263 y = l - vec[i];
264
265 if(y >= 0)
266 x = - fastDelta / x;
267 else
268 x = (y - fastDelta) / x;
269
270 if(x < max)
271 {
272 max = x;
273 sel = i;
274 }
275 }
276 }
277 }
278 }
279
280 update.delta().setSize(int(l_idx - update.delta().indexMem()));
281 update.delta().forceSetup();
282 }
283
284 val = max;
285 maxabs = mabs;
286 return sel;
287 }
288
289 /* See maxDelta() */
290 template <class R>
291 int SPxFastRT<R>::minDelta(
292 R& val,
293 R& maxabs,
294 UpdateVector<R>& update,
295 const VectorBase<R>& lowBound,
296 const VectorBase<R>& upBound,
297 int start,
298 int incr) const
299 {
300 int i, sel;
301 R x, y, max;
302 R u, l;
303 bool leaving = (this->m_type == SPxSolverBase<R>::LEAVE);
304 bool enterrowrep = !leaving && this->thesolver->theRep == SPxSolverBase<R>::ROW;
305
306 R mabs = maxabs;
307
308 const R* up = upBound.get_const_ptr();
309 const R* low = lowBound.get_const_ptr();
310 const R* vec = update.get_const_ptr();
311 const R* upd = update.delta().values();
312 const int* idx = update.delta().indexMem();
313
314 sel = -1;
315 max = val;
316
317 if(update.delta().isSetup())
318 {
319 const int* last = idx + update.delta().size();
320
321 for(idx += start; idx < last; idx += incr)
322 {
323 i = *idx;
324 x = upd[i];
325
326 /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
327 if(leaving && ((iscoid && this->thesolver->isCoBasic(i)) || (!iscoid
328 && this->thesolver->isBasic(i))))
329 continue;
330
331 if(enterrowrep && this->thesolver->baseId(i).isSPxColId()
332 && this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(i))))
333 == SPxBasisBase<R>::Desc::P_FIXED)
334 continue;
335
336 if(x > epsilon)
337 {
338 // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
339 mabs = (x > mabs) ? x : mabs;
340 l = low[i];
341
342 if(l > R(-infinity))
343 {
344 y = l - vec[i];
345
346 if(y >= 0)
347 x = - fastDelta / x;
348 else
349 x = (y - fastDelta) / x;
350
351 if(x > max)
352 {
353 max = x;
354 sel = i;
355 }
356 }
357 }
358 else if(x < -epsilon)
359 {
360 // @todo check wether mabs should be computed only over bounded vars, i.e., in the if block below
361 mabs = (-x > mabs) ? -x : mabs;
362 u = up[i];
363
364 if(u < R(infinity))
365 {
366 y = u - vec[i];
367
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 }
381 }
382 else
383 {
384 /* In this case, the indices of the semi-sparse VectorBase<R> update.delta() are not set up and are filled below. */
385 int* l_idx = update.delta().altIndexMem();
386 R* uval = update.delta().altValues();
387 const R* uend = uval + update.dim();
388 assert(uval == upd);
389
390 for(i = 0; uval < uend; ++uval, ++i)
391 {
392 x = *uval;
393
394 if(x != 0.0)
395 {
396 if(x >= -epsilon && x <= epsilon)
397 {
398 *uval = 0.0;
399 continue;
400 }
401 else
402 *l_idx++ = i;
403
404 /* in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables */
405 if(leaving && ((iscoid && this->thesolver->isCoBasic(i)) || (!iscoid
406 && this->thesolver->isBasic(i))))
407 continue;
408
409 if(enterrowrep && this->thesolver->baseId(i).isSPxColId()
410 && this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(i))))
411 == SPxBasisBase<R>::Desc::P_FIXED)
412 continue;
413
414
415 if(x > epsilon)
416 {
417 mabs = (x > mabs) ? x : mabs;
418 l = low[i];
419
420 if(l > R(-infinity))
421 {
422 y = l - vec[i];
423
424 if(y >= 0)
425 x = - fastDelta / x;
426 else
427 x = (y - fastDelta) / x;
428
429 if(x > max)
430 {
431 max = x;
432 sel = i;
433 }
434 }
435 }
436 else if(x < -epsilon)
437 {
438 mabs = (-x > mabs) ? -x : mabs;
439 u = up[i];
440
441 if(u < R(infinity))
442 {
443 y = u - vec[i];
444
445 if(y <= 0)
446 x = fastDelta / x;
447 else
448 x = (y + fastDelta) / x;
449
450 if(x > max)
451 {
452 max = x;
453 sel = i;
454 }
455 }
456 }
457 }
458 }
459
460 update.delta().setSize(int(l_idx - update.delta().indexMem()));
461 update.delta().forceSetup();
462 }
463
464 val = max;
465 maxabs = mabs;
466
467 return sel;
468 }
469
470 template <class R>
471 int SPxFastRT<R>::maxDelta(
472 R& val,
473 R& maxabs)
474 {
475 assert(this->m_type == SPxSolverBase<R>::ENTER);
476 return maxDelta(val, maxabs,
477 this->thesolver->fVec(), this->thesolver->lbBound(), this->thesolver->ubBound(), 0, 1);
478 }
479
480 template <class R>
481 int SPxFastRT<R>::minDelta(
482 R& val,
483 R& maxabs)
484 {
485 assert(this->m_type == SPxSolverBase<R>::ENTER);
486 return minDelta(val, maxabs,
487 this->thesolver->fVec(), this->thesolver->lbBound(), this->thesolver->ubBound(), 0, 1);
488 }
489
490 template <class R>
491 SPxId SPxFastRT<R>::maxDelta(
492 int& nr,
493 R& max, /* on return: maximum step length */
494 R& maxabs) /* on return: maximum absolute value in delta VectorBase<R> */
495 {
496 /* The following cause side effects on coPvec and pVec - both changes may be needed later in
497 maxSelect(). We can therefore not move the first function after the (indp >= 0) check. */
498 iscoid = true;
499 int indc = maxDelta(max, maxabs,
500 this->thesolver->coPvec(), this->thesolver->lcBound(), this->thesolver->ucBound(), 0, 1);
501 iscoid = false;
502 int indp = maxDelta(max, maxabs,
503 this->thesolver->pVec(), this->thesolver->lpBound(), this->thesolver->upBound(), 0, 1);
504
505 if(indp >= 0)
506 {
507 nr = indp;
508 return this->thesolver->id(indp);
509 }
510
511 if(indc >= 0)
512 {
513 nr = indc;
514 return this->thesolver->coId(indc);
515 }
516
517 nr = -1;
518 return SPxId();
519 }
520
521 template <class R>
522 SPxId SPxFastRT<R>::minDelta(
523 int& nr,
524 R& max,
525 R& maxabs)
526 {
527 /* The following cause side effects on coPvec and pVec - both changes may be needed later in
528 minSelect(). We can therefore not move the first function after the (indp >= 0) check. */
529 iscoid = true;
530 const int indc = minDelta(max, maxabs,
531 this->thesolver->coPvec(), this->thesolver->lcBound(), this->thesolver->ucBound(), 0, 1);
532 iscoid = false;
533 const int indp = minDelta(max, maxabs,
534 this->thesolver->pVec(), this->thesolver->lpBound(), this->thesolver->upBound(), 0, 1);
535
536 if(indp >= 0)
537 {
538 nr = indp;
539 return this->thesolver->id(indp);
540 }
541
542 if(indc >= 0)
543 {
544 nr = indc;
545 return this->thesolver->coId(indc);
546 }
547
548 nr = -1;
549 return SPxId();
550 }
551
552 /* \p best returns the minimum update value such that the corresponding value of \p upd.delta() is
553 * at least \p stab and the update value is smaller than \p max. If no valid update value has been
554 * found \p bestDelta returns the slack to the bound corresponding to the index used for \p best. */
555 template <class R>
556 int SPxFastRT<R>::minSelect(
557 R& val,
558 R& stab,
559 R& best,
560 R& bestDelta,
561 R max,
562 const UpdateVector<R>& update,
563 const VectorBase<R>& lowBound,
564 const VectorBase<R>& upBound,
565 int start,
566 int incr) const
567 {
568 int i;
569 R x, y;
570 bool leaving = this->m_type == SPxSolverBase<R>::LEAVE;
571 bool enterrowrep = !leaving && this->thesolver->theRep == SPxSolverBase<R>::ROW;
572
573 const R* up = upBound.get_const_ptr();
574 const R* low = lowBound.get_const_ptr();
575 const R* vec = update.get_const_ptr();
576 const R* upd = update.delta().values();
577 const int* idx = update.delta().indexMem();
578 const int* last = idx + update.delta().size();
579
580 int nr = -1;
581 int bestNr = -1;
582
583 for(idx += start; idx < last; idx += incr)
584 {
585 i = *idx;
586 x = upd[i];
587
588 // in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables
589 if(leaving && ((iscoid && this->thesolver->isCoBasic(i)) || (!iscoid
590 && this->thesolver->isBasic(i))))
591 continue;
592
593 if(enterrowrep && this->thesolver->baseId(i).isSPxColId()
594 && this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(i))))
595 == SPxBasisBase<R>::Desc::P_FIXED)
596 continue;
597
598 if(x > stab)
599 {
600 y = (low[i] - vec[i]) / x;
601
602 if(y >= max)
603 {
604 val = y;
605 nr = i;
606 stab = x;
607 }
608 else if(y < best)
609 {
610 best = y;
611 bestNr = i;
612 }
613 }
614 else if(x < -stab)
615 {
616 y = (up[i] - vec[i]) / x;
617
618 if(y >= max)
619 {
620 val = y;
621 nr = i;
622 stab = -x;
623 }
624 else if(y < best)
625 {
626 best = y;
627 bestNr = i;
628 }
629 }
630 }
631
632 if(nr < 0 && bestNr > 0)
633 {
634 if(upd[bestNr] < 0)
635 bestDelta = up[bestNr] - vec[bestNr];
636 else
637 bestDelta = vec[bestNr] - low[bestNr];
638 }
639
640 return nr;
641 }
642
643 /* See minSelect() */
644 template <class R>
645 int SPxFastRT<R>::maxSelect(
646 R& val,
647 R& stab,
648 R& best,
649 R& bestDelta,
650 R max,
651 const UpdateVector<R>& update,
652 const VectorBase<R>& lowBound,
653 const VectorBase<R>& upBound,
654 int start,
655 int incr) const
656 {
657 int i;
658 R x, y;
659 bool leaving = this->m_type == SPxSolverBase<R>::LEAVE;
660 bool enterrowrep = !leaving && this->thesolver->theRep == SPxSolverBase<R>::ROW;
661
662 const R* up = upBound.get_const_ptr();
663 const R* low = lowBound.get_const_ptr();
664 const R* vec = update.get_const_ptr();
665 const R* upd = update.delta().values();
666 const int* idx = update.delta().indexMem();
667 const int* last = idx + update.delta().size();
668
669 int nr = -1;
670 int bestNr = -1;
671
672 for(idx += start; idx < last; idx += incr)
673 {
674 i = *idx;
675 x = upd[i];
676
677 // in the dual algorithm, bound flips cannot happen, hence we only consider nonbasic variables
678 if(leaving && ((iscoid && this->thesolver->isCoBasic(i)) || (!iscoid
679 && this->thesolver->isBasic(i))))
680 continue;
681
682 if(enterrowrep && this->thesolver->baseId(i).isSPxColId()
683 && this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(i))))
684 == SPxBasisBase<R>::Desc::P_FIXED)
685 continue;
686
687 if(x > stab)
688 {
689 y = (up[i] - vec[i]) / x;
690
691 if(y <= max)
692 {
693 val = y;
694 nr = i;
695 stab = x;
696 }
697 else if(y > best)
698 {
699 best = y;
700 bestNr = i;
701 }
702 }
703 else if(x < -stab)
704 {
705 y = (low[i] - vec[i]) / x;
706
707 if(y <= max)
708 {
709 val = y;
710 nr = i;
711 stab = -x;
712 }
713 else if(y > best)
714 {
715 best = y;
716 bestNr = i;
717 }
718 }
719 }
720
721 if(nr < 0 && bestNr > 0)
722 {
723 if(upd[bestNr] > 0)
724 bestDelta = up[bestNr] - vec[bestNr];
725 else
726 bestDelta = vec[bestNr] - low[bestNr];
727 }
728
729 return nr;
730 }
731
732 template <class R>
733 int SPxFastRT<R>::maxSelect(
734 R& val,
735 R& stab,
736 R& bestDelta,
737 R max)
738 {
739 R best = R(-infinity);
740 bestDelta = 0.0;
741 assert(this->m_type == SPxSolverBase<R>::ENTER);
742 return maxSelect(val, stab, best, bestDelta, max,
743 this->thesolver->fVec(), this->thesolver->lbBound(), this->thesolver->ubBound(), 0, 1);
744 }
745
746 template <class R>
747 SPxId SPxFastRT<R>::maxSelect(
748 int& nr,
749 R& val,
750 R& stab,
751 R& bestDelta,
752 R max
753 )
754 {
755 int indp, indc;
756 R best = R(-infinity);
757 bestDelta = 0.0;
758 iscoid = true;
759 indc = maxSelect(val, stab, best, bestDelta, max,
760 this->thesolver->coPvec(), this->thesolver->lcBound(), this->thesolver->ucBound(), 0, 1);
761 iscoid = false;
762 indp = maxSelect(val, stab, best, bestDelta, max,
763 this->thesolver->pVec(), this->thesolver->lpBound(), this->thesolver->upBound(), 0, 1);
764
765 if(indp >= 0)
766 {
767 nr = indp;
768 return this->thesolver->id(indp);
769 }
770
771 if(indc >= 0)
772 {
773 nr = indc;
774 return this->thesolver->coId(indc);
775 }
776
777 nr = -1;
778 return SPxId();
779 }
780
781 template <class R>
782 int SPxFastRT<R>::minSelect(
783 R& val,
784 R& stab,
785 R& bestDelta,
786 R max)
787 {
788 R best = R(infinity);
789 bestDelta = 0.0;
790 assert(this->m_type == SPxSolverBase<R>::ENTER);
791 return minSelect(val, stab, best, bestDelta, max,
792 this->thesolver->fVec(), this->thesolver->lbBound(), this->thesolver->ubBound(), 0, 1);
793 }
794
795 template <class R>
796 SPxId SPxFastRT<R>::minSelect(
797 int& nr,
798 R& val,
799 R& stab,
800 R& bestDelta,
801 R max)
802 {
803 R best = R(infinity);
804 bestDelta = 0.0;
805 iscoid = true;
806 int indc = minSelect(val, stab, best, bestDelta, max,
807 this->thesolver->coPvec(), this->thesolver->lcBound(), this->thesolver->ucBound(), 0, 1);
808 iscoid = false;
809 int indp = minSelect(val, stab, best, bestDelta, max,
810 this->thesolver->pVec(), this->thesolver->lpBound(), this->thesolver->upBound(), 0, 1);
811
812 if(indp >= 0)
813 {
814 nr = indp;
815 return this->thesolver->id(indp);
816 }
817
818 if(indc >= 0)
819 {
820 nr = indc;
821 return this->thesolver->coId(indc);
822 }
823
824 nr = -1;
825 return SPxId();
826 }
827
828 template <class R>
829 bool SPxFastRT<R>::maxShortLeave(R& sel, int leave, R maxabs)
830 {
831 assert(leave >= 0);
832 assert(maxabs >= 0);
833
834 sel = this->thesolver->fVec().delta()[leave];
835
836 if(sel > maxabs * SHORTVAL)
837 {
838 sel = (this->thesolver->ubBound()[leave] - this->thesolver->fVec()[leave]) / sel;
839 return true;
840 }
841
842 if(sel < -maxabs * SHORTVAL)
843 {
844 sel = (this->thesolver->lbBound()[leave] - this->thesolver->fVec()[leave]) / sel;
845 return true;
846 }
847
848 return false;
849 }
850
851 template <class R>
852 bool SPxFastRT<R>::minShortLeave(R& sel, int leave, R maxabs)
853 {
854 assert(leave >= 0);
855 assert(maxabs >= 0);
856
857 sel = this->thesolver->fVec().delta()[leave];
858
859 if(sel > maxabs * SHORTVAL)
860 {
861 sel = (this->thesolver->lbBound()[leave] - this->thesolver->fVec()[leave]) / sel;
862 return true;
863 }
864
865 if(sel < -maxabs * SHORTVAL)
866 {
867 sel = (this->thesolver->ubBound()[leave] - this->thesolver->fVec()[leave]) / sel;
868 return true;
869 }
870
871 return false;
872 }
873
874 template <class R>
875 bool SPxFastRT<R>::maxReLeave(R& sel, int leave, R maxabs, bool polish)
876 {
877 UpdateVector<R>& vec = this->thesolver->fVec();
878 VectorBase<R>& low = this->thesolver->lbBound();
879 VectorBase<R>& up = this->thesolver->ubBound();
880
881 if(leave < 0)
882 return true;
883
884 if(up[leave] > low[leave])
885 {
886 R x = vec.delta()[leave];
887
888 if(sel < -fastDelta / maxabs)
889 {
890 sel = 0.0;
891
892 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
893 if(!polish
894 && this->thesolver->dualStatus(this->thesolver->baseId(leave)) != SPxBasisBase<R>::Desc::D_ON_BOTH)
895 {
896 if(x < 0.0)
897 this->thesolver->shiftLBbound(leave, vec[leave]);
898 else
899 this->thesolver->shiftUBbound(leave, vec[leave]);
900 }
901 }
902 }
903 else
904 {
905 sel = 0.0;
906
907 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
908 if(!polish)
909 {
910 this->thesolver->shiftLBbound(leave, vec[leave]);
911 this->thesolver->shiftUBbound(leave, vec[leave]);
912 }
913 }
914
915 return false;
916 }
917
918 template <class R>
919 bool SPxFastRT<R>::minReLeave(R& sel, int leave, R maxabs, bool polish)
920 {
921 UpdateVector<R>& vec = this->thesolver->fVec();
922 VectorBase<R>& low = this->thesolver->lbBound();
923 VectorBase<R>& up = this->thesolver->ubBound();
924
925 if(leave < 0)
926 return true;
927
928 if(up[leave] > low[leave])
929 {
930 R x = vec.delta()[leave];
931
932 if(sel > fastDelta / maxabs)
933 {
934 sel = 0.0;
935
936 if(!polish
937 && this->thesolver->dualStatus(this->thesolver->baseId(leave)) != SPxBasisBase<R>::Desc::D_ON_BOTH)
938 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
939 {
940 if(x > 0.0)
941 this->thesolver->shiftLBbound(leave, vec[leave]);
942 else
943 this->thesolver->shiftUBbound(leave, vec[leave]);
944 }
945 }
946 }
947 else
948 {
949 sel = 0.0;
950
951 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
952 if(!polish)
953 {
954 this->thesolver->shiftLBbound(leave, vec[leave]);
955 this->thesolver->shiftUBbound(leave, vec[leave]);
956 }
957 }
958
959 return false;
960 }
961
962 template <class R>
963 int SPxFastRT<R>::selectLeave(R& val, R, bool polish)
964 {
965 R maxabs, max, sel;
966 int leave = -1;
967 int cnt = 0;
968
969 assert(this->m_type == SPxSolverBase<R>::ENTER);
970
971 // force instable pivot iff true (see explanation in enter.cpp and spxsolve.hpp)
972 bool instable = this->solver()->instableEnter;
973 R lowstab = LOWSTAB;
974 assert(!instable || this->solver()->instableEnterId.isValid());
975
976 resetTols();
977
978 if(val > epsilon)
979 {
980 do
981 {
982 // phase 1:
983 max = val;
984 maxabs = 0.0;
985 leave = maxDelta(max, maxabs);
986
987 assert(leave < 0 || !(this->thesolver->baseId(leave).isSPxColId()) ||
988 this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(
989 leave)))) != SPxBasisBase<R>::Desc::P_FIXED);
990
991 if(max == val || leave == -1)
992 {
993 assert(max == val && leave == -1);
994 return -1;
995 }
996
997 if(!maxShortLeave(sel, leave, maxabs))
998 {
999 // phase 2:
1000 R stab, bestDelta;
1001
1002 stab = 100.0 * minStability(maxabs);
1003
1004 // force instable pivot iff instable is true (see explanation in enter.hpp and spxsolve.hpp)
1005 if(instable)
1006 leave = maxSelect(sel, lowstab, bestDelta, max);
1007 else
1008 leave = maxSelect(sel, stab, bestDelta, max);
1009
1010 if(bestDelta < DELTA_SHIFT * TRIES)
1011 cnt++;
1012 else
1013 cnt += TRIES;
1014 }
1015
1016 if(!maxReLeave(sel, leave, maxabs, polish))
1017 break;
1018
1019 relax();
1020 }
1021 while(cnt < TRIES);
1022 }
1023 else if(val < -epsilon)
1024 {
1025 do
1026 {
1027 max = val;
1028 maxabs = 0;
1029 leave = minDelta(max, maxabs);
1030
1031 assert(leave < 0 || !(this->thesolver->baseId(leave).isSPxColId()) ||
1032 this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(
1033 leave)))) != SPxBasisBase<R>::Desc::P_FIXED);
1034
1035 if(max == val || leave == -1)
1036 {
1037 assert(max == val && leave == -1);
1038 return -1;
1039 }
1040
1041 if(!minShortLeave(sel, leave, maxabs))
1042 {
1043 // phase 2:
1044 R stab, bestDelta;
1045
1046 stab = 100.0 * minStability(maxabs);
1047
1048 // force instable pivot iff instable is true (see explanation in enter.hpp and spxsolve.hpp)
1049 if(instable)
1050 leave = minSelect(sel, lowstab, bestDelta, max);
1051 else
1052 leave = minSelect(sel, stab, bestDelta, max);
1053
1054 assert(leave < 0 || !(this->thesolver->baseId(leave).isSPxColId())
1055 || this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(
1056 leave)))) != SPxBasisBase<R>::Desc::P_FIXED);
1057
1058 if(bestDelta < DELTA_SHIFT * TRIES)
1059 cnt++;
1060 else
1061 cnt += TRIES;
1062 }
1063
1064 if(!minReLeave(sel, leave, maxabs, polish))
1065 break;
1066
1067 relax();
1068 }
1069 while(cnt < TRIES);
1070 }
1071 else
1072 return -1;
1073
1074 MSG_DEBUG(
1075
1076 if(leave >= 0)
1077 std::cout
1078 << "DFSTRT01 "
1079 << this->thesolver->basis().iteration() << "("
1080 << std::setprecision(6) << this->thesolver->value() << ","
1081 << std::setprecision(2) << this->thesolver->basis().stability() << "):"
1082 << leave << "\t"
1083 << std::setprecision(4) << sel << " "
1084 << std::setprecision(4) << this->thesolver->fVec().delta()[leave] << " "
1085 << std::setprecision(6) << maxabs
1086 << std::endl;
1087 else
1088 std::cout << "DFSTRT02 " << this->thesolver->basis().iteration()
1089 << ": skipping instable pivot" << std::endl;
1090 )
1091
1092 if(polish && leave >= 0)
1093 {
1094 assert(this->thesolver->rep() == SPxSolverBase<R>::COLUMN);
1095 SPxId leaveId = this->thesolver->baseId(leave);
1096
1097 // decide whether the chosen leave index contributes to the polishing objective
1098 if(this->thesolver->polishObj == SPxSolverBase<R>::POLISH_INTEGRALITY)
1099 {
1100 // only allow (integer) variables to leave the basis
1101 if(leaveId.isSPxRowId())
1102 return -1;
1103 else if(this->thesolver->integerVariables.size() == this->thesolver->nCols())
1104 {
1105 if(leaveId.isSPxColId() && this->thesolver->integerVariables[this->thesolver->number(leaveId)] == 0)
1106 return -1;
1107 }
1108 }
1109 else if(this->thesolver->polishObj == SPxSolverBase<R>::POLISH_FRACTIONALITY)
1110 {
1111 // only allow slacks and continuous variables to leave the basis
1112 if(this->thesolver->integerVariables.size() == this->thesolver->nCols())
1113 {
1114 if(this->thesolver->baseId(leave).isSPxColId()
1115 && this->thesolver->integerVariables[this->thesolver->number(leaveId)] == 1)
1116 return -1;
1117 }
1118 else if(this->thesolver->baseId(leave).isSPxColId())
1119 return -1;
1120 }
1121 }
1122
1123 if(leave >= 0 || minStab > 2 * this->solver()->epsilon())
1124 {
1125 val = sel;
1126
1127 if(leave >= 0)
1128 tighten();
1129 }
1130
1131 assert(leave < 0 || !(this->thesolver->baseId(leave).isSPxColId())
1132 || this->thesolver->desc().colStatus(this->thesolver->number(SPxColId(this->thesolver->baseId(
1133 leave)))) != SPxBasisBase<R>::Desc::P_FIXED);
1134
1135 return leave;
1136 }
1137
1138
1139 template <class R>
1140 bool SPxFastRT<R>::maxReEnter(R& sel,
1141 R maxabs,
1142 const SPxId& id,
1143 int nr,
1144 bool polish)
1145 {
1146 R x, d;
1147 VectorBase<R>* up;
1148 VectorBase<R>* low;
1149
1150 UpdateVector<R>& pvec = this->thesolver->pVec();
1151 SSVectorBase<R>& pupd = this->thesolver->pVec().delta();
1152 VectorBase<R>& upb = this->thesolver->upBound();
1153 VectorBase<R>& lpb = this->thesolver->lpBound();
1154 UpdateVector<R>& cvec = this->thesolver->coPvec();
1155 SSVectorBase<R>& cupd = this->thesolver->coPvec().delta();
1156 VectorBase<R>& ucb = this->thesolver->ucBound();
1157 VectorBase<R>& lcb = this->thesolver->lcBound();
1158
1159 if(this->thesolver->isCoId(id))
1160 {
1161 if(this->thesolver->isCoBasic(nr))
1162 {
1163 cupd.clearIdx(nr);
1164 return true;
1165 }
1166
1167 x = cvec[nr];
1168 d = cupd[nr];
1169 up = &ucb;
1170 low = &lcb;
1171
1172 if(d < 0.0)
1173 sel = (lcb[nr] - cvec[nr]) / d;
1174 else
1175 sel = (ucb[nr] - cvec[nr]) / d;
1176 }
1177 else if(this->thesolver->isId(id))
1178 {
1179 pvec[nr] = this->thesolver->vector(nr) * cvec;
1180
1181 if(this->thesolver->isBasic(nr))
1182 {
1183 pupd.clearIdx(nr);
1184 return true;
1185 }
1186
1187 x = pvec[nr];
1188 d = pupd[nr];
1189 up = &upb;
1190 low = &lpb;
1191
1192 if(d < 0.0)
1193 sel = (lpb[nr] - pvec[nr]) / d;
1194 else
1195 sel = (upb[nr] - pvec[nr]) / d;
1196 }
1197 else
1198 return true;
1199
1200 if((*up)[nr] != (*low)[nr])
1201 {
1202 if(sel < -fastDelta / maxabs)
1203 {
1204 sel = 0.0;
1205
1206 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
1207 if(!polish)
1208 {
1209 if(d > 0.0)
1210 {
1211 this->thesolver->theShift -= (*up)[nr];
1212 (*up)[nr] = x;
1213 this->thesolver->theShift += (*up)[nr];
1214 }
1215 else
1216 {
1217 this->thesolver->theShift += (*low)[nr];
1218 (*low)[nr] = x;
1219 this->thesolver->theShift -= (*low)[nr];
1220 }
1221 }
1222 }
1223 }
1224 else
1225 {
1226 sel = 0.0;
1227
1228 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
1229 if(!polish)
1230 {
1231 if(x > (*up)[nr])
1232 this->thesolver->theShift += x - (*up)[nr];
1233 else
1234 this->thesolver->theShift += (*low)[nr] - x;
1235
1236 (*up)[nr] = (*low)[nr] = x;
1237 }
1238 }
1239
1240 return false;
1241 }
1242
1243 template <class R>
1244 bool SPxFastRT<R>::minReEnter(
1245 R& sel,
1246 R maxabs,
1247 const SPxId& id,
1248 int nr,
1249 bool polish)
1250 {
1251 R x, d;
1252 VectorBase<R>* up;
1253 VectorBase<R>* low;
1254
1255 UpdateVector<R>& pvec = this->thesolver->pVec();
1256 SSVectorBase<R>& pupd = this->thesolver->pVec().delta();
1257 VectorBase<R>& upb = this->thesolver->upBound();
1258 VectorBase<R>& lpb = this->thesolver->lpBound();
1259 UpdateVector<R>& cvec = this->thesolver->coPvec();
1260 SSVectorBase<R>& cupd = this->thesolver->coPvec().delta();
1261 VectorBase<R>& ucb = this->thesolver->ucBound();
1262 VectorBase<R>& lcb = this->thesolver->lcBound();
1263
1264 if(this->thesolver->isCoId(id))
1265 {
1266 if(this->thesolver->isCoBasic(nr))
1267 {
1268 cupd.clearIdx(nr);
1269 return true;
1270 }
1271
1272 x = cvec[nr];
1273 d = cupd[nr];
1274 up = &ucb;
1275 low = &lcb;
1276
1277 if(d > 0.0)
1278 sel = (this->thesolver->lcBound()[nr] - cvec[nr]) / d;
1279 else
1280 sel = (this->thesolver->ucBound()[nr] - cvec[nr]) / d;
1281 }
1282
1283 else if(this->thesolver->isId(id))
1284 {
1285 pvec[nr] = this->thesolver->vector(nr) * cvec;
1286
1287 if(this->thesolver->isBasic(nr))
1288 {
1289 pupd.clearIdx(nr);
1290 return true;
1291 }
1292
1293 x = pvec[nr];
1294 d = pupd[nr];
1295 up = &upb;
1296 low = &lpb;
1297
1298 if(d > 0.0)
1299 sel = (this->thesolver->lpBound()[nr] - pvec[nr]) / d;
1300 else
1301 sel = (this->thesolver->upBound()[nr] - pvec[nr]) / d;
1302 }
1303
1304 else
1305 return true;
1306
1307 if((*up)[nr] != (*low)[nr])
1308 {
1309 if(sel > fastDelta / maxabs)
1310 {
1311 sel = 0.0;
1312
1313 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
1314 if(!polish)
1315 {
1316 if(d < 0.0)
1317 {
1318 this->thesolver->theShift -= (*up)[nr];
1319 (*up)[nr] = x;
1320 this->thesolver->theShift += (*up)[nr];
1321 }
1322 else
1323 {
1324 this->thesolver->theShift += (*low)[nr];
1325 (*low)[nr] = x;
1326 this->thesolver->theShift -= (*low)[nr];
1327 }
1328 }
1329 }
1330 }
1331 else
1332 {
1333 sel = 0.0;
1334
1335 // prevent shifts in polishing mode to avoid a final cleanup step (i.e. simplex type switch)
1336 if(!polish)
1337 {
1338 if(x > (*up)[nr])
1339 this->thesolver->theShift += x - (*up)[nr];
1340 else
1341 this->thesolver->theShift += (*low)[nr] - x;
1342
1343 (*up)[nr] = (*low)[nr] = x;
1344 }
1345 }
1346
1347 return false;
1348 }
1349
1350 template <class R>
1351 bool SPxFastRT<R>::shortEnter(
1352 const SPxId& enterId,
1353 int nr,
1354 R max,
1355 R maxabs) const
1356 {
1357 if(this->thesolver->isCoId(enterId))
1358 {
1359 if(max != 0.0)
1360 {
1361 R x = this->thesolver->coPvec().delta()[nr];
1362
1363 if(x < maxabs * SHORTVAL && -x < maxabs * SHORTVAL)
1364 return false;
1365 }
1366
1367 return true;
1368 }
1369 else if(this->thesolver->isId(enterId))
1370 {
1371 if(max != 0.0)
1372 {
1373 R x = this->thesolver->pVec().delta()[nr];
1374
1375 if(x < maxabs * SHORTVAL && -x < maxabs * SHORTVAL)
1376 return false;
1377 }
1378
1379 return true;
1380 }
1381
1382 return false;
1383 }
1384
1385 template <class R>
1386 SPxId SPxFastRT<R>::selectEnter(R& val, int, bool polish)
1387 {
1388 SPxId enterId;
1389 R max, sel;
1390 R maxabs = 0.0;
1391 int nr;
1392 int cnt = 0;
1393
1394 assert(this->m_type == SPxSolverBase<R>::LEAVE);
1395
1396 // force instable pivot iff true (see explanation in leave.hpp and spxsolve.hpp)
1397 bool instable = this->solver()->instableLeave;
1398 R lowstab = LOWSTAB;
1399 assert(!instable || this->solver()->instableLeaveNum >= 0);
1400
1401 resetTols();
1402 sel = 0.0;
1403
1404 if(val > epsilon)
1405 {
1406 do
1407 {
1408 maxabs = 0.0;
1409 max = val;
1410
1411 enterId = maxDelta(nr, max, maxabs);
1412
1413 if(!enterId.isValid())
1414 return enterId;
1415
1416 assert(max >= 0.0);
1417 assert(!enterId.isValid() || !this->solver()->isBasic(enterId));
1418
1419 if(!shortEnter(enterId, nr, max, maxabs))
1420 {
1421 R bestDelta, stab;
1422
1423 stab = minStability(maxabs);
1424
1425 // force instable pivot iff instable is true (see explanation in leave.hpp and spxsolve.hpp)
1426 if(instable)
1427 {
1428 enterId = maxSelect(nr, sel, lowstab, bestDelta, max);
1429 }
1430 else
1431 {
1432 enterId = maxSelect(nr, sel, stab, bestDelta, max);
1433 }
1434
1435 if(bestDelta < DELTA_SHIFT * TRIES)
1436 cnt++;
1437 else
1438 cnt += TRIES;
1439 }
1440
1441 if(!maxReEnter(sel, maxabs, enterId, nr, polish))
1442 break;
1443
1444 relax();
1445 }
1446 while(cnt < TRIES);
1447 }
1448 else if(val < -epsilon)
1449 {
1450 do
1451 {
1452 maxabs = 0.0;
1453 max = val;
1454 enterId = minDelta(nr, max, maxabs);
1455
1456 if(!enterId.isValid())
1457 return enterId;
1458
1459 assert(max <= 0.0);
1460 assert(!enterId.isValid() || !this->solver()->isBasic(enterId));
1461
1462 if(!shortEnter(enterId, nr, max, maxabs))
1463 {
1464 R bestDelta, stab;
1465
1466 stab = minStability(maxabs);
1467
1468 // force instable pivot iff instable is true (see explanation in leave.hpp and spxsolve.hpp)
1469 if(instable)
1470 {
1471 enterId = minSelect(nr, sel, lowstab, bestDelta, max);
1472 }
1473 else
1474 {
1475 enterId = minSelect(nr, sel, stab, bestDelta, max);
1476 }
1477
1478 if(bestDelta < DELTA_SHIFT * TRIES)
1479 cnt++;
1480 else
1481 cnt += TRIES;
1482 }
1483
1484 if(!minReEnter(sel, maxabs, enterId, nr, polish))
1485 break;
1486
1487 relax();
1488 }
1489 while(cnt < TRIES);
1490 }
1491
1492 MSG_DEBUG(
1493
1494 if(enterId.isValid())
1495 {
1496 assert(!enterId.isValid() || !this->solver()->isBasic(enterId));
1497
1498 R x;
1499
1500 if(this->thesolver->isCoId(enterId))
1501 x = this->thesolver->coPvec().delta()[ this->thesolver->number(enterId) ];
1502 else
1503 x = this->thesolver->pVec().delta()[ this->thesolver->number(enterId) ];
1504
1505 std::cout << "DFSTRT03 " << this->thesolver->basis().iteration() << ": "
1506 << sel << '\t' << x << " (" << maxabs << ")" << std::endl;
1507 }
1508 else
1509 std::cout << "DFSTRT04 " << this->thesolver->basis().iteration()
1510 << ": skipping instable pivot" << std::endl;
1511 )
1512
1513 if(polish && enterId.isValid())
1514 {
1515 assert(this->thesolver->rep() == SPxSolverBase<R>::ROW);
1516
1517 // decide whether the chosen entering index contributes to the polishing objective
1518 if(this->thesolver->polishObj == SPxSolverBase<R>::POLISH_INTEGRALITY)
1519 {
1520 // only allow (integer) variables to enter the basis
1521 if(enterId.isSPxRowId())
1522 return SPxId();
1523 else if(this->thesolver->integerVariables.size() == this->thesolver->nCols()
1524 && this->thesolver->integerVariables[this->thesolver->number(enterId)] == 0)
1525 return SPxId();
1526 }
1527 else if(this->thesolver->polishObj == SPxSolverBase<R>::POLISH_FRACTIONALITY)
1528 {
1529 // only allow slacks and continuous variables to enter the basis
1530 if(this->thesolver->integerVariables.size() == this->thesolver->nCols())
1531 {
1532 if(enterId.isSPxColId() && this->thesolver->integerVariables[this->thesolver->number(enterId)] == 1)
1533 return SPxId();
1534 }
1535 else if(enterId.isSPxColId())
1536 return SPxId();
1537 }
1538 }
1539
1540
1541 if(enterId.isValid() || minStab > 2 * epsilon)
1542 {
1543 val = sel;
1544
1545 if(enterId.isValid())
1546 tighten();
1547 }
1548
1549 assert(!enterId.isValid() || !this->solver()->isBasic(enterId));
1550
1551 return enterId;
1552 }
1553
1554 template <class R>
1555 void SPxFastRT<R>::load(SPxSolverBase<R>* spx)
1556 {
1557 this->thesolver = spx;
1558 setType(spx->type());
1559 }
1560
1561 template <class R>
1562 void SPxFastRT<R>::setType(typename SPxSolverBase<R>::Type type)
1563 {
1564 this->m_type = type;
1565
1566 minStab = MINSTAB;
1567 fastDelta = this->delta;
1568 }
1569 } // namespace soplex
1570