Scippy

SoPlex

Sequential object-oriented simPlex

leave.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2015 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /* Updating the Basis for Leaving Variables
17  */
18 #include <assert.h>
19 #include <stdio.h>
20 
21 #include "spxdefines.h"
22 #include "spxpricer.h"
23 #include "spxsolver.h"
24 #include "spxratiotester.h"
25 #include "spxout.h"
26 #include "exceptions.h"
27 
28 namespace soplex
29 {
30 static const Real reject_leave_tol = 1e-10; // = LOWSTAB as defined in spxfastrt.cpp
31 
32 /*
33  Vector |fTest| gives the feasibility test of all basic variables. For its
34  computation |fVec|, |theUBbound| and |theLBbound| must be setup correctly.
35  Values of |fTest| $<0$ represent infeasible variables, which are eligible
36  for leaving the basis in the simplex loop.
37  */
39 {
40 
41  assert(type() == LEAVE);
42 
43  Real theeps = entertol();
45  int ninfeasibilities = 0;
46  int sparsitythreshold = (int) (sparsePricingFactor * dim());
47 
48  for( int i = 0; i < dim(); ++i )
49  {
50  theCoTest[i] = ((*theFvec)[i] > theUBbound[i])
51  ? theUBbound[i] - (*theFvec)[i]
52  : (*theFvec)[i] - theLBbound[i];
53 
54  if( remainingRoundsLeave == 0 )
55  {
56  if( theCoTest[i] < -theeps )
57  {
60  ++ninfeasibilities;
61  }
62  else
64  if( ninfeasibilities > sparsitythreshold )
65  {
66  MSG_INFO2( (*spxout), (*spxout) << " --- using dense pricing"
67  << std::endl; )
69  sparsePricingLeave = false;
70  ninfeasibilities = 0;
71  }
72  }
73  }
74 
75  if( ninfeasibilities == 0 && !sparsePricingLeave )
76  {
78  }
79  else if( ninfeasibilities <= sparsitythreshold && !sparsePricingLeave )
80  {
81  MSG_INFO2( (*spxout),
82  std::streamsize prec = spxout->precision();
83  if( hyperPricingLeave )
84  (*spxout) << " --- using hypersparse pricing, ";
85  else
86  (*spxout) << " --- using sparse pricing, ";
87  (*spxout) << "sparsity: "
88  << std::setw(6) << std::fixed << std::setprecision(4)
89  << (Real) ninfeasibilities/dim()
90  << std::scientific << std::setprecision(int(prec))
91  << std::endl;
92  )
93  sparsePricingLeave = true;
94  }
95 }
96 
98 {
99  const IdxSet& idx = theFvec->idx();
100  Vector& ftest = theCoTest; // |== fTest()|
101  assert(&ftest == &fTest());
102 
103  assert(type() == LEAVE);
104 
105  updateViols.clear();
106  Real theeps = entertol();
107  for (int j = idx.size() - 1; j >= 0; --j)
108  {
109  int i = idx.index(j);
110 
111  ftest[i] = ((*theFvec)[i] > theUBbound[i])
112  ? theUBbound[i] - (*theFvec)[i]
113  : (*theFvec)[i] - theLBbound[i];
114  if( sparsePricingLeave && ftest[i] < -theeps )
115  {
116  assert(remainingRoundsLeave == 0);
118  {
119  // this can cause problems - we cannot keep on adding indeces to infeasibilities,
120  // because they are not deleted in hyper mode...
121 // if( !hyperPricingLeave )
124  }
125  if( hyperPricingLeave )
126  updateViols.addIdx(i);
127  }
128  }
129  // if boundflips were performed, we need to update these indices as well
130  if( boundflips > 0 )
131  {
132  Real eps = epsilon();
133  for( int i = 0; i < solveVector3->dim(); ++i )
134  {
135  if( (*solveVector3)[i] > eps || (*solveVector3)[i] < -eps )
136  {
137  ftest[i] = ((*theFvec)[i] > theUBbound[i]) ? theUBbound[i] - (*theFvec)[i] : (*theFvec)[i] - theLBbound[i];
138  if( sparsePricingLeave && ftest[i] < -theeps )
139  {
140  assert(remainingRoundsLeave == 0);
141  if( !isInfeasible[i] )
142  {
144  isInfeasible[i] = true;
145  }
146  }
147  }
148  }
149  }
150 }
151 
152 
153 /* compute statistics on leaving variable
154  Compute a set of statistical values on the variable selected for leaving the
155  basis.
156  */
158  int leaveIdx,
159  SPxBasis::Desc::Status& leaveStat,
160  SPxId& leaveId,
161  Real& leaveMax,
162  Real& leavebound,
163  int& leaveNum,
164  Real& objChange)
165 {
166  SPxBasis::Desc& ds = desc();
167  leaveId = baseId(leaveIdx);
168 
169  if (leaveId.isSPxRowId())
170  {
171  leaveNum = number(SPxRowId(leaveId));
172  leaveStat = ds.rowStatus(leaveNum);
173 
174  assert(isBasic(leaveStat));
175  switch (leaveStat)
176  {
178  assert( rep() == ROW );
179  ds.rowStatus(leaveNum) = dualRowStatus(leaveNum);
180  leavebound = 0;
181  leaveMax = -infinity;
182  break;
184  assert( rep() == ROW );
185  ds.rowStatus(leaveNum) = dualRowStatus(leaveNum);
186  leavebound = 0;
187  leaveMax = infinity;
188  break;
190  assert( rep() == ROW );
191  throw SPxInternalCodeException("XLEAVE01 This should never happen.");
193  assert( rep() == COLUMN );
194  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_FIXED;
195  assert(lhs(leaveNum) == rhs(leaveNum));
196  leavebound = -rhs(leaveNum);
197  if ((*theFvec)[leaveIdx] < theLBbound[leaveIdx])
198  leaveMax = infinity;
199  else
200  leaveMax = -infinity;
201  break;
203  assert( rep() == COLUMN );
204  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_ON_UPPER;
205  leavebound = -rhs(leaveNum); // slack !!
206  leaveMax = infinity;
207  objChange += theLRbound[leaveNum] * rhs(leaveNum);
208  break;
210  assert( rep() == COLUMN );
211  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_ON_LOWER;
212  leavebound = -lhs(leaveNum); // slack !!
213  leaveMax = -infinity;
214  objChange += theURbound[leaveNum] * lhs(leaveNum);
215  break;
217  assert( rep() == COLUMN );
218  if ((*theFvec)[leaveIdx] > theLBbound[leaveIdx])
219  {
220  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_ON_LOWER;
221  theLRbound[leaveNum] = -infinity;
222  leavebound = -lhs(leaveNum); // slack !!
223  leaveMax = -infinity;
224  objChange += theURbound[leaveNum] * lhs(leaveNum);
225  }
226  else
227  {
228  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_ON_UPPER;
229  theURbound[leaveNum] = infinity;
230  leavebound = -rhs(leaveNum); // slack !!
231  leaveMax = infinity;
232  objChange += theLRbound[leaveNum] * rhs(leaveNum);
233  }
234  break;
235 
236  default:
237  throw SPxInternalCodeException("XLEAVE02 This should never happen.");
238  }
239  MSG_DEBUG( std::cout << "DLEAVE51 SPxSolver::getLeaveVals() : row " << leaveNum
240  << ": " << leaveStat
241  << " -> " << ds.rowStatus(leaveNum)
242  << " objChange: " << objChange
243  << std::endl; )
244  }
245 
246  else
247  {
248  assert(leaveId.isSPxColId());
249  leaveNum = number(SPxColId(leaveId));
250  leaveStat = ds.colStatus(leaveNum);
251 
252  assert(isBasic(leaveStat));
253  switch (leaveStat)
254  {
256  assert( rep() == ROW );
257  ds.colStatus(leaveNum) = dualColStatus(leaveNum);
258  leavebound = 0;
259  leaveMax = -infinity;
260  break;
262  assert( rep() == ROW );
263  ds.colStatus(leaveNum) = dualColStatus(leaveNum);
264  leavebound = 0;
265  leaveMax = infinity;
266  break;
268  assert( rep() == ROW );
269  ds.colStatus(leaveNum) = dualColStatus(leaveNum);
270  if ((*theFvec)[leaveIdx] < theLBbound[leaveIdx])
271  {
272  leavebound = theLBbound[leaveIdx];
273  leaveMax = -infinity;
274  }
275  else
276  {
277  leavebound = theUBbound[leaveIdx];
278  leaveMax = infinity;
279  }
280  break;
281 
283  assert( rep() == COLUMN );
284  assert(SPxLP::upper(leaveNum) == SPxLP::lower(leaveNum));
285  ds.colStatus(leaveNum) = SPxBasis::Desc::P_FIXED;
286  leavebound = SPxLP::upper(leaveNum);
287  objChange += maxObj(leaveNum) * leavebound;
288  if ((*theFvec)[leaveIdx] < theLBbound[leaveIdx])
289  leaveMax = infinity;
290  else
291  leaveMax = -infinity;
292  break;
294  assert( rep() == COLUMN );
295  ds.colStatus(leaveNum) = SPxBasis::Desc::P_ON_UPPER;
296  leavebound = SPxLP::upper(leaveNum);
297  objChange += theUCbound[leaveNum] * leavebound;
298  leaveMax = -infinity;
299  break;
301  assert( rep() == COLUMN );
302  ds.colStatus(leaveNum) = SPxBasis::Desc::P_ON_LOWER;
303  leavebound = SPxLP::lower(leaveNum);
304  objChange += theLCbound[leaveNum] * leavebound;
305  leaveMax = infinity;
306  break;
308  assert( rep() == COLUMN );
309  if ((*theFvec)[leaveIdx] > theUBbound[leaveIdx])
310  {
311  leaveMax = -infinity;
312  leavebound = SPxLP::upper(leaveNum);
313  objChange += theUCbound[leaveNum] * leavebound;
314  theLCbound[leaveNum] = -infinity;
315  ds.colStatus(leaveNum) = SPxBasis::Desc::P_ON_UPPER;
316  }
317  else
318  {
319  leaveMax = infinity;
320  leavebound = SPxLP::lower(leaveNum);
321  objChange += theLCbound[leaveNum] * leavebound;
322  theUCbound[leaveNum] = infinity;
323  ds.colStatus(leaveNum) = SPxBasis::Desc::P_ON_LOWER;
324  }
325  break;
326  default:
327  throw SPxInternalCodeException("XLEAVE03 This should never happen.");
328  }
329  MSG_DEBUG( std::cout << "DLEAVE52 SPxSolver::getLeaveVals() : col " << leaveNum
330  << ": " << leaveStat
331  << " -> " << ds.colStatus(leaveNum)
332  << " objChange: " << objChange
333  << std::endl; )
334  }
335 }
336 
338  Real leaveMax,
339  SPxId enterId,
340  Real& enterBound,
341  Real& newUBbound,
342  Real& newLBbound,
343  Real& newCoPrhs,
344  Real& objChange
345 )
346 {
347  SPxBasis::Desc& ds = desc();
348 
349  enterBound = 0;
350  if (enterId.isSPxRowId())
351  {
352  int idx = number(SPxRowId(enterId));
353  SPxBasis::Desc::Status enterStat = ds.rowStatus(idx);
354 
355  switch (enterStat)
356  {
358  assert(rep() == ROW);
359  if (thePvec->delta()[idx] * leaveMax < 0)
360  newCoPrhs = theLRbound[idx];
361  else
362  newCoPrhs = theURbound[idx];
363  newUBbound = infinity;
364  newLBbound = -infinity;
366  break;
368  assert(rep() == ROW);
369  newUBbound = 0;
370  newLBbound = -infinity;
372  newCoPrhs = theLRbound[idx];
373  break;
375  assert(rep() == ROW);
376  newUBbound = infinity;
377  newLBbound = 0;
379  newCoPrhs = theURbound[idx];
380  break;
382  assert(rep() == ROW);
383  if (leaveMax * thePvec->delta()[idx] < 0)
384  {
385  newUBbound = 0;
386  newLBbound = -infinity;
388  newCoPrhs = theLRbound[idx];
389  }
390  else
391  {
392  newUBbound = infinity;
393  newLBbound = 0;
395  newCoPrhs = theURbound[idx];
396  }
397  break;
398 
400  assert(rep() == COLUMN);
401  ds.rowStatus(idx) = dualRowStatus(idx);
402  if (lhs(idx) > -infinity)
403  theURbound[idx] = theLRbound[idx];
404  newCoPrhs = theLRbound[idx]; // slack !!
405  newUBbound = -lhs(idx);
406  newLBbound = -rhs(idx);
407  enterBound = -rhs(idx);
408  objChange -= newCoPrhs * rhs(idx);
409  break;
411  assert(rep() == COLUMN);
412  ds.rowStatus(idx) = dualRowStatus(idx);
413  if (rhs(idx) < infinity)
414  theLRbound[idx] = theURbound[idx];
415  newCoPrhs = theURbound[idx]; // slack !!
416  newLBbound = -rhs(idx);
417  newUBbound = -lhs(idx);
418  enterBound = -lhs(idx);
419  objChange -= newCoPrhs * lhs(idx);
420  break;
422  assert(rep() == COLUMN);
423 #if 1
424  throw SPxInternalCodeException("XLEAVE04 This should never happen.");
425 #else
426  MSG_ERROR( std::cerr << "ELEAVE53 ERROR: not yet debugged!" << std::endl; )
427  ds.rowStatus(idx) = dualRowStatus(idx);
428  newCoPrhs = theURbound[idx]; // slack !!
429  newUBbound = infinity;
430  newLBbound = -infinity;
431  enterBound = 0;
432 #endif
433  break;
435  assert(rep() == COLUMN);
436  MSG_ERROR( std::cerr << "ELEAVE54 "
437  << "ERROR! Tried to put a fixed row variable into the basis: "
438  << "idx=" << idx
439  << ", lhs=" << lhs(idx)
440  << ", rhs=" << rhs(idx) << std::endl; )
441  throw SPxInternalCodeException("XLEAVE05 This should never happen.");
442 
443  default:
444  throw SPxInternalCodeException("XLEAVE06 This should never happen.");
445  }
446  MSG_DEBUG( std::cout << "DLEAVE55 SPxSolver::getLeaveVals2(): row " << idx
447  << ": " << enterStat
448  << " -> " << ds.rowStatus(idx)
449  << " objChange: " << objChange
450  << std::endl; )
451  }
452 
453  else
454  {
455  assert(enterId.isSPxColId());
456  int idx = number(SPxColId(enterId));
457  SPxBasis::Desc::Status enterStat = ds.colStatus(idx);
458 
459  switch (enterStat)
460  {
462  assert(rep() == ROW);
463  newUBbound = 0;
464  newLBbound = -infinity;
466  newCoPrhs = theLCbound[idx];
467  break;
469  assert(rep() == ROW);
470  newUBbound = infinity;
471  newLBbound = 0;
473  newCoPrhs = theUCbound[idx];
474  break;
476  assert(rep() == ROW);
477  newUBbound = infinity;
478  newLBbound = -infinity;
479  newCoPrhs = theLCbound[idx];
481  break;
483  assert(rep() == ROW);
484  if (leaveMax * theCoPvec->delta()[idx] < 0)
485  {
486  newUBbound = 0;
487  newLBbound = -infinity;
489  newCoPrhs = theLCbound[idx];
490  }
491  else
492  {
493  newUBbound = infinity;
494  newLBbound = 0;
496  newCoPrhs = theUCbound[idx];
497  }
498  break;
499 
501  assert(rep() == COLUMN);
502  ds.colStatus(idx) = dualColStatus(idx);
503  if (SPxLP::lower(idx) > -infinity)
504  theLCbound[idx] = theUCbound[idx];
505  newCoPrhs = theUCbound[idx];
506  newUBbound = SPxLP::upper(idx);
507  newLBbound = SPxLP::lower(idx);
508  enterBound = SPxLP::upper(idx);
509  objChange -= newCoPrhs * enterBound;
510  break;
512  assert(rep() == COLUMN);
513  ds.colStatus(idx) = dualColStatus(idx);
514  if (SPxLP::upper(idx) < infinity)
515  theUCbound[idx] = theLCbound[idx];
516  newCoPrhs = theLCbound[idx];
517  newUBbound = SPxLP::upper(idx);
518  newLBbound = SPxLP::lower(idx);
519  enterBound = SPxLP::lower(idx);
520  objChange -= newCoPrhs * enterBound;
521  break;
523  assert(rep() == COLUMN);
524  ds.colStatus(idx) = dualColStatus(idx);
525  if (thePvec->delta()[idx] * leaveMax > 0)
526  newCoPrhs = theUCbound[idx];
527  else
528  newCoPrhs = theLCbound[idx];
529  newUBbound = SPxLP::upper(idx);
530  newLBbound = SPxLP::lower(idx);
531  enterBound = 0;
532  break;
534  assert(rep() == COLUMN);
535  MSG_ERROR( std::cerr << "ELEAVE56 "
536  << "ERROR! Tried to put a fixed column variable into the basis. "
537  << "idx=" << idx
538  << ", lower=" << lower(idx)
539  << ", upper=" << upper(idx) << std::endl; )
540  throw SPxInternalCodeException("XLEAVE07 This should never happen.");
541  default:
542  throw SPxInternalCodeException("XLEAVE08 This should never happen.");
543  }
544 
545  MSG_DEBUG( std::cout << "DLEAVE57 SPxSolver::getLeaveVals2(): col " << idx
546  << ": " << enterStat
547  << " -> " << ds.colStatus(idx)
548  << " objChange: " << objChange
549  << std::endl; )
550  }
551 
552 }
553 
555  int leaveNum,
556  SPxId leaveId,
557  SPxBasis::Desc::Status leaveStat,
558  const SVector* //newVec
559 )
560 {
561  SPxBasis::Desc& ds = desc();
562  if (leaveId.isSPxRowId())
563  {
564  MSG_DEBUG( std::cout << "DLEAVE58 rejectLeave() : row " << leaveNum
565  << ": " << ds.rowStatus(leaveNum)
566  << " -> " << leaveStat << std::endl; )
567 
568  if (leaveStat == SPxBasis::Desc::D_ON_BOTH)
569  {
570  if (ds.rowStatus(leaveNum) == SPxBasis::Desc::P_ON_LOWER)
571  theLRbound[leaveNum] = theURbound[leaveNum];
572  else
573  theURbound[leaveNum] = theLRbound[leaveNum];
574  }
575  ds.rowStatus(leaveNum) = leaveStat;
576  }
577  else
578  {
579  MSG_DEBUG( std::cout << "DLEAVE59 rejectLeave() : col " << leaveNum
580  << ": " << ds.colStatus(leaveNum)
581  << " -> " << leaveStat << std::endl; )
582 
583  if (leaveStat == SPxBasis::Desc::D_ON_BOTH)
584  {
585  if (ds.colStatus(leaveNum) == SPxBasis::Desc::P_ON_UPPER)
586  theLCbound[leaveNum] = theUCbound[leaveNum];
587  else
588  theUCbound[leaveNum] = theLCbound[leaveNum];
589  }
590  ds.colStatus(leaveNum) = leaveStat;
591  }
592 }
593 
594 
595 bool SPxSolver::leave(int leaveIdx)
596 {
597  assert(leaveIdx < dim() && leaveIdx >= 0);
598  assert(type() == LEAVE);
599  assert(initialized);
600 
601  bool instable = instableLeave;
602  assert(!instable || instableLeaveNum >= 0);
603 
604  /*
605  Before performing the actual basis update, we must determine, how this
606  is to be accomplished.
607  When using steepest edge pricing this solve is already performed by the pricer
608  */
609  if (theCoPvec->delta().isSetup() && theCoPvec->delta().size() == 0)
610  {
611  coSolve(theCoPvec->delta(), unitVecs[leaveIdx]);
612  }
613 #ifdef ENABLE_ADDITIONAL_CHECKS
614  else
615  {
616  SSVector tmp(dim(), epsilon());
617  tmp.clear();
618  coSolve(tmp, unitVecs[leaveIdx]);
619  tmp -= theCoPvec->delta();
620  if (tmp.length() > leavetol()) {
621  // This happens very frequently and does usually not hurt, so print
622  // these warnings only with verbose level INFO2 and higher.
623  MSG_INFO2( (*spxout), (*spxout) << "WLEAVE60 iteration=" << basis().iteration()
624  << ": coPvec.delta error = " << tmp.length()
625  << std::endl; )
626  }
627  }
628 #endif // ENABLE_ADDITIONAL_CHECKS
629 
630  setupPupdate();
631 
632  assert(thePvec->isConsistent());
633  assert(theCoPvec->isConsistent());
634 
635  SPxBasis::Desc::Status leaveStat; // status of leaving var
636  SPxId leaveId; // id of leaving var
637  SPxId none; // invalid id used if leave fails
638  Real leaveMax; // maximium lambda of leaving var
639  Real leavebound; // current fVec value of leaving var
640  int leaveNum; // number of leaveId in bounds
641  Real objChange = 0.0; // amount of change in the objective function
642 
643  getLeaveVals(leaveIdx, leaveStat, leaveId, leaveMax, leavebound, leaveNum, objChange);
644 
645  if (m_numCycle > m_maxCycle)
646  {
647  if (leaveMax > 0)
648  perturbMaxLeave();
649  else
650  perturbMinLeave();
651  //@ m_numCycle /= 2;
652  // perturbation invalidates the currently stored nonbasic value
654  }
655  //@ testBounds();
656 
657  Real enterVal = leaveMax;
658  boundflips = 0;
659  Real oldShift = theShift;
660  SPxId enterId = theratiotester->selectEnter(enterVal, leaveIdx);
661  if (theShift != oldShift)
662  {
663  MSG_DEBUG( std::cout << "DLEAVE71 trigger recomputation of nonbasic value due to shifts in ratiotest" << std::endl; )
665  }
666 
667  assert(!enterId.isValid() || !isBasic(enterId));
668 
669  instableLeaveNum = -1;
670  instableLeave = false;
671 
672  /*
673  No variable could be selected to enter the basis and even the leaving
674  variable is unbounded.
675  */
676  if (!enterId.isValid())
677  {
678  /* the following line originally was below in "rejecting leave" case;
679  we need it in the unbounded/infeasible case, too, to have the
680  correct basis size */
681  rejectLeave(leaveNum, leaveId, leaveStat);
682  change(-1, none, 0);
683  objChange = 0.0; // the nonbasicValue is not supposed to be updated in this case
684 
685  if (enterVal != leaveMax)
686  {
687  MSG_DEBUG( std::cout << "DLEAVE61 rejecting leave A (leaveIdx=" << leaveIdx
688  << ", theCoTest=" << theCoTest[leaveIdx] << ")"
689  << std::endl; )
690 
691  /* In the LEAVE algorithm, when for a selected leaving variable we find only
692  an instable entering variable, then the basis change is not conducted.
693  Instead, we save the leaving variable's index in instableLeaveNum and scale
694  theCoTest[leaveIdx] down by some factor, hoping to find a different leaving
695  variable with a stable entering variable.
696  If this fails, however, and no more leaving variable is found, we have to
697  perform the instable basis change using instableLeaveNum. In this (and only
698  in this) case, the flag instableLeave is set to true.
699 
700  enterVal != leaveMax is the case that selectEnter has found only an instable entering
701  variable. We store this leaving variable for later -- if we are not already in the
702  instable case: then we continue and conclude unboundedness/infeasibility */
703  if (!instable)
704  {
705  instableLeaveNum = leaveIdx;
706 
707  // Note: These changes do not survive a refactorization
708  instableLeaveVal = theCoTest[leaveIdx];
709  theCoTest[leaveIdx] = 0.0;
710 
711  return true;
712  }
713  }
714 
715  if (lastUpdate() > 1)
716  {
717  MSG_INFO3( (*spxout), (*spxout) << "ILEAVE01 factorization triggered in "
718  << "leave() for feasibility test" << std::endl; )
719  factorize();
720 
721  /* after a factorization, the leaving column/row might not be infeasible or suboptimal anymore, hence we do
722  * not try to call leave(leaveIdx), but rather return to the main solving loop and call the pricer again
723  */
724  return true;
725  }
726 
727  /* do not exit with status infeasible or unbounded if there is only a very small violation */
728  if (spxAbs(enterVal) < leavetol())
729  {
730  MSG_INFO3( (*spxout), (*spxout) << "ILEAVE11 clean up step to reduce numerical errors" << std::endl; )
731 
732  computeFrhs();
734  computeFtest();
735 
736  return true;
737  }
738  MSG_INFO3( (*spxout), (*spxout) << "ILEAVE02 unboundedness/infeasibility found "
739  << "in leave()" << std::endl; )
740 
741  if (rep() != COLUMN)
743  else
744  {
745  int sign;
746  int i;
747 
748  dualFarkas.clear();
750  sign = (enterVal > 0 ? -1 : +1);
751  for( i = 0; i < coPvec().delta().size(); ++i )
752  dualFarkas.add(coPvec().delta().index(i), sign * coPvec().delta().value(i));
753 
755  }
756  return false;
757  }
758  else
759  {
760  /*
761  If an entering variable has been found, a regular basis update is to
762  be performed.
763  */
764  if (enterId != baseId(leaveIdx))
765  {
766  const SVector& newVector = *enterVector(enterId);
767  // update feasibility vectors
768  if( solveVector2 != NULL && solveVector3 != NULL )
769  {
770  assert(solveVector2->isConsistent());
771  assert(solveVector2rhs->isSetup());
772  assert(solveVector3->isConsistent());
773  assert(solveVector3rhs->isSetup());
774  assert(boundflips > 0);
776  *solveVector2,
777  *solveVector3,
778  newVector,
780  *solveVector3rhs);
781 
782  // perform update of basic solution
783  primVec -= (*solveVector3);
784  MSG_INFO3( (*spxout), (*spxout) << "ILBFRT02 "
785  << "breakpoints passed / bounds flipped = " << boundflips
786  << std::endl; )
788  }
789  else if( solveVector2 != NULL )
790  {
791  assert(solveVector2->isConsistent());
792  assert(solveVector2rhs->isSetup());
793 
795  *solveVector2,
796  newVector,
797  *solveVector2rhs);
798  }
799  else if( solveVector3 != NULL )
800  {
801  assert(solveVector3->isConsistent());
802  assert(solveVector3rhs->isSetup());
803  assert(boundflips > 0);
805  *solveVector3,
806  newVector,
807  *solveVector3rhs);
808 
809  // perform update of basic solution
810  primVec -= (*solveVector3);
811  MSG_INFO3( (*spxout), (*spxout) << "ILBFRT02 "
812  << "breakpoints passed / bounds flipped = " << boundflips
813  << std::endl; )
815  }
816  else
817  SPxBasis::solve4update (theFvec->delta(), newVector);
818 
819 #ifdef ENABLE_ADDITIONAL_CHECKS
820  {
821  SSVector tmp(dim(), epsilon());
822  SPxBasis::solve(tmp, newVector);
823  tmp -= fVec().delta();
824  if (tmp.length() > entertol()) {
825  // This happens very frequently and does usually not hurt, so print
826  // these warnings only with verbose level INFO2 and higher.
827  MSG_INFO2( (*spxout), (*spxout) << "WLEAVE62\t(" << tmp.length() << ")\n"; )
828  }
829  }
830 #endif // ENABLE_ADDITIONAL_CHECKS
831 
832 
833  if (spxAbs(theFvec->delta()[leaveIdx]) < reject_leave_tol)
834  {
835  if (instable)
836  {
837  /* We are in the case that for all leaving variables only instable entering
838  variables were found: Thus, above we already accepted such an instable
839  entering variable. Now even this seems to be impossible, thus we conclude
840  unboundedness/infeasibility. */
841  MSG_INFO3( (*spxout), (*spxout) << "ILEAVE03 unboundedness/infeasibility found "
842  << "in leave()" << std::endl; )
843 
844  rejectLeave(leaveNum, leaveId, leaveStat);
845  change(-1, none, 0);
846  objChange = 0.0; // the nonbasicValue is not supposed to be updated in this case
847 
848  /**@todo if shift() is not zero we must not conclude unboundedness */
849  if (rep() == ROW)
850  {
851  Real sign;
852 
853  primalRay.clear();
855  sign = (enterVal > 0 ? 1.0 : -1.0);
856 
857  for( int i = 0; i < coPvec().delta().size(); ++i )
858  primalRay.add(coPvec().delta().index(i), sign * coPvec().delta().value(i));
859 
861  }
862  else
863  {
864  Real sign;
865  int i;
866 
867  dualFarkas.clear();
869  sign = (enterVal > 0 ? -1.0 : +1.0);
870 
871  for( i = 0; i < coPvec().delta().size(); ++i )
872  dualFarkas.add(coPvec().delta().index(i), sign * coPvec().delta().value(i));
873 
875  }
876 
877  return false;
878  }
879  else
880  {
881  theFvec->delta().clear();
882  rejectLeave(leaveNum, leaveId, leaveStat, &newVector);
883  change(-1, none, 0);
884  objChange = 0.0; // the nonbasicValue is not supposed to be updated in this case
885 
886  MSG_DEBUG( std::cout << "DLEAVE63 rejecting leave B (leaveIdx=" << leaveIdx
887  << ", theCoTest=" << theCoTest[leaveIdx]
888  << ")" << std::endl; )
889 
890  // Note: These changes do not survive a refactorization
891  theCoTest[leaveIdx] *= 0.01;
892 
893  return true;
894  }
895  }
896 
897  // process leaving variable
898  if (leavebound > epsilon() || leavebound < -epsilon())
899  theFrhs->multAdd(-leavebound, baseVec(leaveIdx));
900 
901  // process entering variable
902  Real enterBound;
903  Real newUBbound;
904  Real newLBbound;
905  Real newCoPrhs;
906 
907  try
908  {
909  getLeaveVals2(leaveMax, enterId, enterBound, newUBbound, newLBbound, newCoPrhs, objChange);
910  }
911  catch( const SPxException& F )
912  {
913  rejectLeave(leaveNum, leaveId, leaveStat);
914  change(-1, none, 0);
915  objChange = 0.0; // the nonbasicValue is not supposed to be updated in this case
916  throw F;
917  }
918 
919  theUBbound[leaveIdx] = newUBbound;
920  theLBbound[leaveIdx] = newLBbound;
921  (*theCoPrhs)[leaveIdx] = newCoPrhs;
922 
923  if (enterBound > epsilon() || enterBound < -epsilon())
924  theFrhs->multAdd(enterBound, newVector);
925 
926  // update pricing vectors
927  theCoPvec->value() = enterVal;
928  thePvec->value() = enterVal;
929  if (enterVal > epsilon() || enterVal < -epsilon())
930  doPupdate();
931 
932  // update feasibility vector
933  theFvec->value() = -((*theFvec)[leaveIdx] - leavebound)
934  / theFvec->delta()[leaveIdx];
935  theFvec->update();
936  (*theFvec)[leaveIdx] = enterBound - theFvec->value();
937  updateFtest();
938 
939  // update objective funtion value
940  updateNonbasicValue(objChange);
941 
942  // change basis matrix
943  change(leaveIdx, enterId, &newVector, &(theFvec->delta()));
944  }
945 
946  /*
947  No entering vector has been selected from the basis. However, if the
948  shift amount for |coPvec| is bounded, we are in the case, that the
949  entering variable is moved from one bound to its other, before any of
950  the basis feasibility variables reaches their bound. This may only
951  happen in primal/columnwise case with upper and lower bounds on
952  variables.
953  */
954  else
955  {
956  // @todo update obj function value here!!!
957  assert(rep() == ROW);
958  SPxBasis::Desc& ds = desc();
959 
960  change(leaveIdx, none, 0);
961 
962  if (leaveStat == SPxBasis::Desc::P_ON_UPPER)
963  {
964  if (leaveId.isSPxRowId())
965  {
966  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_ON_LOWER;
967  (*theCoPrhs)[leaveIdx] = theLRbound[leaveNum];
968  }
969  else
970  {
971  ds.colStatus(leaveNum) = SPxBasis::Desc::P_ON_LOWER;
972  (*theCoPrhs)[leaveIdx] = theLCbound[leaveNum];
973  }
974  theUBbound[leaveIdx] = 0;
975  theLBbound[leaveIdx] = -infinity;
976  }
977  else
978  {
979  assert( leaveStat == SPxBasis::Desc::P_ON_LOWER );
980  if (leaveId.isSPxRowId())
981  {
982  ds.rowStatus(leaveNum) = SPxBasis::Desc::P_ON_UPPER;
983  (*theCoPrhs)[leaveIdx] = theURbound[leaveNum];
984  }
985  else
986  {
987  ds.colStatus(leaveNum) = SPxBasis::Desc::P_ON_UPPER;
988  (*theCoPrhs)[leaveIdx] = theUCbound[leaveNum];
989  }
990  theUBbound[leaveIdx] = infinity;
991  theLBbound[leaveIdx] = 0;
992  }
993 
994  // update copricing vector
995  theCoPvec->value() = enterVal;
996  thePvec->value() = enterVal;
997  if (enterVal > epsilon() || enterVal < -epsilon())
998  doPupdate();
999 
1000  // update feasibility vectors
1001  theFvec->value() = 0;
1002  theCoTest[leaveIdx] *= -1;
1003  }
1004 
1005  if ((leaveMax > entertol() && enterVal <= entertol()) || (leaveMax < -entertol() && enterVal >= -entertol()))
1006  {
1007  if ((theUBbound[leaveIdx] < infinity || theLBbound[leaveIdx] > -infinity)
1008  && leaveStat != SPxBasis::Desc::P_FREE
1009  && leaveStat != SPxBasis::Desc::D_FREE)
1010  m_numCycle++;
1011  }
1012  else
1013  m_numCycle /= 2;
1014 
1015 #ifdef ENABLE_ADDITIONAL_CHECKS
1016  {
1017  DVector tmp = fVec();
1018  multBaseWith(tmp);
1019  tmp -= fRhs();
1020  if (tmp.length() > entertol())
1021  {
1022  // This happens very frequently and does usually not hurt, so print
1023  // these warnings only with verbose level INFO2 and higher.
1024  MSG_INFO2( (*spxout), (*spxout) << "WLEAVE64\t" << basis().iteration()
1025  << ": fVec error = " << tmp.length() << std::endl; )
1026  SPxBasis::solve(tmp, fRhs());
1027  tmp -= fVec();
1028  MSG_INFO2( (*spxout), (*spxout) << "WLEAVE65\t(" << tmp.length() << ")\n"; )
1029  }
1030  }
1031 #endif // ENABLE_ADDITIONAL_CHECKS
1032 
1033  return true;
1034  }
1035 }
1036 } // namespace soplex