Scippy

SoPlex

Sequential object-oriented simPlex

solverational.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 #ifndef SOPLEX_LEGACY
17 #include <iostream>
18 #include <assert.h>
19 
20 #include "soplex.h"
21 #include "statistics.h"
22 #include "slufactor_rational.h"
23 #include "ratrecon.h"
24 
25 namespace soplex
26 {
27  /// solves rational LP
29  {
30  bool hasUnboundedRay = false;
31  bool infeasibilityNotCertified = false;
32  bool unboundednessNotCertified = false;
33 
34  // start timing
37 
38  // remember that last solve was rational
40 
41  // ensure that the solver has the original problem
42  if( !_isRealLPLoaded )
43  {
44  assert(_realLP != &_solver);
45 
48  _realLP = &_solver;
49  _isRealLPLoaded = true;
50  }
51  // during the rational solve, we always store basis information in the basis arrays
52  else if( _hasBasis )
53  {
57  }
58 
59  // store objective, bounds, and sides of real LP in case they will be modified during iterative refinement
60  _storeLPReal();
61 
62  // deactivate objective limit in floating-point solver
64  {
65  MSG_INFO2( spxout, spxout << "Deactivating objective limit.\n" );
66  }
67 
69 
71 
72  // apply lifting to reduce range of nonzero matrix coefficients
74  _lift();
75 
76  // force column representation
77  ///@todo implement row objectives with row representation
78  int oldRepresentation = intParam(SoPlex::REPRESENTATION);
80 
81  // force ratio test (avoid bound flipping)
82  int oldRatiotester = intParam(SoPlex::RATIOTESTER);
84 
85  ///@todo implement handling of row objectives in Cplex interface
86 #ifdef SOPLEX_WITH_CPX
87  int oldEqtrans = boolParam(SoPlex::EQTRANS);
89 #endif
90 
91  // introduce slack variables to transform inequality constraints into equations
94 
95  _storedBasis = false;
96 
97  bool stoppedTime;
98  bool stoppedIter;
99  do
100  {
101  bool primalFeasible = false;
102  bool dualFeasible = false;
103  bool infeasible = false;
104  bool unbounded = false;
105  bool error = false;
106  stoppedTime = false;
107  stoppedIter = false;
108 
109  // solve problem with iterative refinement and recovery mechanism
110  _performOptIRStable(_solRational, !unboundednessNotCertified, !infeasibilityNotCertified, 0,
111  primalFeasible, dualFeasible, infeasible, unbounded, stoppedTime, stoppedIter, error);
112 
113  // case: an unrecoverable error occured
114  if( error )
115  {
117  break;
118  }
119  // case: stopped due to some limit
120  else if( stoppedTime )
121  {
123  break;
124  }
125  else if( stoppedIter )
126  {
128  break;
129  }
130  // case: unboundedness detected for the first time
131  else if( unbounded && !unboundednessNotCertified )
132  {
133  SolRational solUnbounded;
134 
135  _performUnboundedIRStable(solUnbounded, hasUnboundedRay, stoppedTime, stoppedIter, error);
136 
137  assert(!hasUnboundedRay || solUnbounded.hasPrimalRay());
138  assert(!solUnbounded.hasPrimalRay() || hasUnboundedRay);
139 
140  if( error )
141  {
142  MSG_INFO1( spxout, spxout << "Error while testing for unboundedness.\n" );
144  break;
145  }
146 
147  if( hasUnboundedRay )
148  {
149  MSG_INFO1( spxout, spxout << "Dual infeasible. Primal unbounded ray available.\n" );
150  }
151  else
152  {
153  MSG_INFO1( spxout, spxout << "Dual feasible. Rejecting primal unboundedness.\n" );
154  }
155 
156  unboundednessNotCertified = !hasUnboundedRay;
157 
158  if( stoppedTime )
159  {
161  break;
162  }
163  else if( stoppedIter )
164  {
166  break;
167  }
168 
169  _performFeasIRStable(_solRational, infeasible, stoppedTime, stoppedIter, error);
170 
171  ///@todo this should be stored already earlier, possible switch use solRational above and solFeas here
172  if( hasUnboundedRay )
173  {
174  _solRational._primalRay = solUnbounded._primalRay;
176  }
177 
178  if( error )
179  {
180  MSG_INFO1( spxout, spxout << "Error while testing for feasibility.\n" );
182  break;
183  }
184  else if( stoppedTime )
185  {
187  break;
188  }
189  else if( stoppedIter )
190  {
192  break;
193  }
194  else if( infeasible )
195  {
196  MSG_INFO1( spxout, spxout << "Primal infeasible. Dual Farkas ray available.\n" );
198  break;
199  }
200  else if( hasUnboundedRay )
201  {
202  MSG_INFO1( spxout, spxout << "Primal feasible and unbounded.\n" );
204  break;
205  }
206  else
207  {
208  MSG_INFO1( spxout, spxout << "Primal feasible and bounded.\n" );
209  continue;
210  }
211  }
212  // case: infeasibility detected
213  else if( infeasible && !infeasibilityNotCertified )
214  {
215  _storeBasis();
216 
217  _performFeasIRStable(_solRational, infeasible, stoppedTime, stoppedIter, error);
218 
219  if( error )
220  {
221  MSG_INFO1( spxout, spxout << "Error while testing for infeasibility.\n" );
223  _restoreBasis();
224  break;
225  }
226 
227  infeasibilityNotCertified = !infeasible;
228 
229  if( stoppedTime )
230  {
232  _restoreBasis();
233  break;
234  }
235  else if( stoppedIter )
236  {
238  _restoreBasis();
239  break;
240  }
241 
242  if( infeasible && boolParam(SoPlex::TESTDUALINF) )
243  {
244  SolRational solUnbounded;
245 
246  _performUnboundedIRStable(solUnbounded, hasUnboundedRay, stoppedTime, stoppedIter, error);
247 
248  assert(!hasUnboundedRay || solUnbounded.hasPrimalRay());
249  assert(!solUnbounded.hasPrimalRay() || hasUnboundedRay);
250 
251  if( error )
252  {
253  MSG_INFO1( spxout, spxout << "Error while testing for dual infeasibility.\n" );
255  _restoreBasis();
256  break;
257  }
258 
259  if( hasUnboundedRay )
260  {
261  MSG_INFO1( spxout, spxout << "Dual infeasible. Primal unbounded ray available.\n" );
262  _solRational._primalRay = solUnbounded._primalRay;
264  }
265  else if( solUnbounded._isDualFeasible )
266  {
267  MSG_INFO1( spxout, spxout << "Dual feasible. Storing dual multipliers.\n" );
268  _solRational._dual = solUnbounded._dual;
269  _solRational._redCost = solUnbounded._redCost;
271  }
272  else
273  {
274  assert(false);
275  MSG_INFO1( spxout, spxout << "Not dual infeasible.\n" );
276  }
277  }
278 
279  _restoreBasis();
280 
281  if( infeasible )
282  {
283  MSG_INFO1( spxout, spxout << "Primal infeasible. Dual Farkas ray available.\n" );
285  break;
286  }
287  else if( hasUnboundedRay )
288  {
289  MSG_INFO1( spxout, spxout << "Primal feasible and unbounded.\n" );
291  break;
292  }
293  else
294  {
295  MSG_INFO1( spxout, spxout << "Primal feasible. Optimizing again.\n" );
296  continue;
297  }
298  }
299  else if( primalFeasible && dualFeasible )
300  {
301  MSG_INFO1( spxout, spxout << "Solved to optimality.\n" );
303  break;
304  }
305  else
306  {
307  MSG_INFO1( spxout, spxout << "Terminating without success.\n" );
308  break;
309  }
310  }
311  while( !_isSolveStopped(stoppedTime, stoppedIter) );
312 
313  ///@todo set status to ABORT_VALUE if optimal solution exceeds objective limit
314 
316  _hasSolRational = true;
317 
318  // restore original problem
321 
322 #ifdef SOPLEX_WITH_CPX
323  setBoolParam(SoPlex::EQTRANS, oldEqtrans);
324 #endif
325 
326  // reset representation and ratio test
327  setIntParam(SoPlex::REPRESENTATION, oldRepresentation);
328  setIntParam(SoPlex::RATIOTESTER, oldRatiotester);
329 
330  // undo lifting
333 
334  // restore objective, bounds, and sides of real LP in case they have been modified during iterative refinement
335  _restoreLPReal();
336 
337  // since the real LP is loaded in the solver, we need to also pass the basis information to the solver if
338  // available
339  if( _hasBasis )
340  {
341  assert(_isRealLPLoaded);
344  }
345 
346  // stop timing
348  }
349 
350 
351 
352  /// solves current problem with iterative refinement and recovery mechanism
354  SolRational& sol,
355  bool acceptUnbounded,
356  bool acceptInfeasible,
357  int minRounds,
358  bool& primalFeasible,
359  bool& dualFeasible,
360  bool& infeasible,
361  bool& unbounded,
362  bool& stoppedTime,
363  bool& stoppedIter,
364  bool& error)
365  {
366  // start rational solving timing
368 
369  primalFeasible = false;
370  dualFeasible = false;
371  infeasible = false;
372  unbounded = false;
373  stoppedTime = false;
374  stoppedIter = false;
375  error = false;
376 
377  // set working tolerances in floating-point solver
380 
381  // declare vectors and variables
383 
384  _modLower.reDim(numColsRational(), false);
385  _modUpper.reDim(numColsRational(), false);
386  _modLhs.reDim(numRowsRational(), false);
387  _modRhs.reDim(numRowsRational(), false);
388  _modObj.reDim(numColsRational(), false);
389 
390  DVectorReal primalReal(numColsRational());
391  DVectorReal dualReal(numRowsRational());
392 
393  Rational boundsViolation;
394  Rational sideViolation;
395  Rational redCostViolation;
396  Rational dualViolation;
397  Rational primalScale;
398  Rational dualScale;
399  Rational maxScale;
400 
401  // solve original LP
402  MSG_INFO1( spxout, spxout << "Initial floating-point solve . . .\n" );
403 
404  if( _hasBasis )
405  {
406  assert(_basisStatusRows.size() == numRowsRational());
407  assert(_basisStatusCols.size() == numColsRational());
410  }
411 
412  for( int r = numRowsRational() - 1; r >= 0; r-- )
413  {
414  assert(_solver.maxRowObj(r) == 0.0);
415  }
416 
418  result = _solveRealStable(acceptUnbounded, acceptInfeasible, primalReal, dualReal, _basisStatusRows, _basisStatusCols, _hasBasis);
419 
420  // evaluate result
421  switch( result )
422  {
423  case SPxSolver::OPTIMAL:
424  MSG_INFO1( spxout, spxout << "Floating-point optimal.\n" );
425  break;
427  MSG_INFO1( spxout, spxout << "Floating-point infeasible.\n" );
428  // the floating-point solve returns a Farkas ray if and only if the simplifier was not used, which is exactly
429  // the case when a basis could be returned
430  if( _hasBasis )
431  {
432  sol._dualFarkas = dualReal;
433  sol._hasDualFarkas = true;
434  }
435  else
436  sol._hasDualFarkas = false;
437  infeasible = true;
438  return;
440  MSG_INFO1( spxout, spxout << "Floating-point unbounded.\n" );
441  unbounded = true;
442  return;
444  stoppedTime = true;
445  return;
447  stoppedIter = true;
448  return;
449  default:
450  error = true;
451  return;
452  }
453 
455 
456  // store floating-point solution of original LP as current rational solution and ensure that solution vectors have
457  // right dimension; ensure that solution is aligned with basis
458  sol._primal.reDim(numColsRational(), false);
459  sol._slacks.reDim(numRowsRational(), false);
460  sol._dual.reDim(numRowsRational(), false);
461  sol._redCost.reDim(numColsRational(), false);
462  sol._isPrimalFeasible= true;
463  sol._isDualFeasible = true;
464 
465  for( int c = numColsRational() - 1; c >= 0; c-- )
466  {
467  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
468 
469  if( basisStatusCol == SPxSolver::ON_LOWER )
470  sol._primal[c] = lowerRational(c);
471  else if( basisStatusCol == SPxSolver::ON_UPPER )
472  sol._primal[c] = upperRational(c);
473  else if( basisStatusCol == SPxSolver::FIXED )
474  {
475  // it may happen that lower and upper are only equal in the real LP but different in the rational LP; we do
476  // not check this to avoid rational comparisons, but simply switch the basis status to the lower bound; this
477  // is necessary, because for fixed variables any reduced cost is feasible
478  sol._primal[c] = lowerRational(c);
479  basisStatusCol = SPxSolver::ON_LOWER;
480  }
481  else if( basisStatusCol == SPxSolver::ZERO )
482  sol._primal[c] = 0;
483  else
484  sol._primal[c] = primalReal[c];
485  }
487 
488  int dualSize = 0;
489  for( int r = numRowsRational() - 1; r >= 0; r-- )
490  {
491  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
492 
493  // it may happen that left-hand and right-hand side are different in the rational, but equal in the real LP,
494  // leading to a fixed basis status; this is critical because rows with fixed basis status are ignored in the
495  // computation of the dual violation; to avoid rational comparisons we do not check this but simply switch to
496  // the left-hand side status
497  if( basisStatusRow == SPxSolver::FIXED )
498  basisStatusRow = SPxSolver::ON_LOWER;
499 
500  {
501  sol._dual[r] = dualReal[r];
502  if( dualReal[r] != 0.0 )
503  dualSize++;
504  }
505  }
506  // we assume that the objective function vector has less nonzeros than the reduced cost vector, and so multiplying
507  // with -1 first and subtracting the dual activity should be faster than adding the dual activity and negating
508  // afterwards
511 
512  // initial scaling factors are one
513  primalScale = _rationalPosone;
514  dualScale = _rationalPosone;
515 
516  // control progress
517  Rational maxViolation;
518  Rational bestViolation = _rationalPosInfty;
519  const Rational violationImprovementFactor = 0.9;
520  const Rational errorCorrectionFactor = 1.1;
521  Rational errorCorrection = 2;
522  int numFailedRefinements = 0;
523 
524  // store basis status in case solving modified problem failed
525  DataArray< SPxSolver::VarStatus > basisStatusRowsFirst;
526  DataArray< SPxSolver::VarStatus > basisStatusColsFirst;
527 
528  // refinement loop
529  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
530  const int maxDimRational = numColsRational() > numRowsRational() ? numColsRational() : numRowsRational();
531  SolRational factorSol;
532  bool factorSolNewBasis = true;
533  int lastStallRefinements = 0;
534  int nextRatrecRefinement = 0;
535  do
536  {
537  // decrement minRounds counter
538  minRounds--;
539 
540  MSG_DEBUG( std::cout << "Computing primal violations.\n" );
541 
542  // compute violation of bounds
543  boundsViolation = 0;
544  for( int c = numColsRational() - 1; c >= 0; c-- )
545  {
546  // lower bound
548  if( _lowerFinite(_colTypes[c]) )
549  {
550  if( lowerRational(c) == 0 )
551  {
552  _modLower[c] = sol._primal[c];
553  _modLower[c] *= -1;
554  if( _modLower[c] > boundsViolation )
555  boundsViolation = _modLower[c];
556  }
557  else
558  {
559  _modLower[c] = lowerRational(c);
560  _modLower[c] -= sol._primal[c];
561  if( _modLower[c] > boundsViolation )
562  boundsViolation = _modLower[c];
563  }
564  }
565 
566  // upper bound
568  if( _upperFinite(_colTypes[c]) )
569  {
570  if( upperRational(c) == 0 )
571  {
572  _modUpper[c] = sol._primal[c];
573  _modUpper[c] *= -1;
574  if( _modUpper[c] < -boundsViolation )
575  boundsViolation = -_modUpper[c];
576  }
577  else
578  {
579  _modUpper[c] = upperRational(c);
580  _modUpper[c] -= sol._primal[c];
581  if( _modUpper[c] < -boundsViolation )
582  boundsViolation = -_modUpper[c];
583  }
584  }
585  }
586 
587  // compute violation of sides
588  sideViolation = 0;
589  for( int r = numRowsRational() - 1; r >= 0; r-- )
590  {
591  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
592 
593  // left-hand side
594  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
595  if( _lowerFinite(_rowTypes[r]) )
596  {
597  if( lhsRational(r) == 0 )
598  {
599  _modLhs[r] = sol._slacks[r];
600  _modLhs[r] *= -1;
601  }
602  else
603  {
604  _modLhs[r] = lhsRational(r);
605  _modLhs[r] -= sol._slacks[r];
606  }
607 
608  if( _modLhs[r] > sideViolation )
609  sideViolation = _modLhs[r];
610  // if the activity is feasible, but too far from the bound, this violates complementary slackness; we
611  // count it as side violation here
612  else if( basisStatusRow == SPxSolver::ON_LOWER && _modLhs[r] < -sideViolation )
613  sideViolation = -_modLhs[r];
614  }
615 
616  // right-hand side
617  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
618  if( _upperFinite(_rowTypes[r]) )
619  {
620  if( rhsRational(r) == 0 )
621  {
622  _modRhs[r] = sol._slacks[r];
623  _modRhs[r] *= -1;
624  }
625  else
626  {
627  _modRhs[r] = rhsRational(r);
628  _modRhs[r] -= sol._slacks[r];
629  }
630 
631  if( _modRhs[r] < -sideViolation )
632  sideViolation = -_modRhs[r];
633  // if the activity is feasible, but too far from the bound, this violates complementary slackness; we
634  // count it as side violation here
635  else if( basisStatusRow == SPxSolver::ON_UPPER && _modRhs[r] > sideViolation )
636  sideViolation = _modRhs[r];
637  }
638  }
639 
640  MSG_DEBUG( std::cout << "Computing dual violations.\n" );
641 
642  // compute reduced cost violation
643  redCostViolation = 0;
644  for( int c = numColsRational() - 1; c >= 0; c-- )
645  {
646  if( _colTypes[c] == RANGETYPE_FIXED )
647  continue;
648 
649  const SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
650  assert(basisStatusCol != SPxSolver::FIXED);
651 
652  if( ((maximizing && basisStatusCol != SPxSolver::ON_LOWER) || (!maximizing && basisStatusCol != SPxSolver::ON_UPPER))
653  && sol._redCost[c] < -redCostViolation )
654  {
655  MSG_DEBUG( std::cout << "basisStatusCol = " << basisStatusCol
656  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
657  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
658  << ", sol._redCost[c] = " << rationalToString(sol._redCost[c])
659  << "\n" );
660  redCostViolation = -sol._redCost[c];
661  }
662 
663  if( ((maximizing && basisStatusCol != SPxSolver::ON_UPPER) || (!maximizing && basisStatusCol != SPxSolver::ON_LOWER))
664  && sol._redCost[c] > redCostViolation )
665  {
666  MSG_DEBUG( std::cout << "basisStatusCol = " << basisStatusCol
667  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
668  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
669  << ", sol._redCost[c] = " << rationalToString(sol._redCost[c])
670  << "\n" );
671  redCostViolation = sol._redCost[c];
672  }
673  }
674 
675  // compute dual violation
676  dualViolation = 0;
677  for( int r = numRowsRational() - 1; r >= 0; r-- )
678  {
679  if( _rowTypes[r] == RANGETYPE_FIXED )
680  continue;
681 
682  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
683  assert(basisStatusRow != SPxSolver::FIXED);
684 
685  if( ((maximizing && basisStatusRow != SPxSolver::ON_LOWER) || (!maximizing && basisStatusRow != SPxSolver::ON_UPPER))
686  && sol._dual[r] < -dualViolation )
687  {
688  MSG_DEBUG( std::cout << "basisStatusRow = " << basisStatusRow
689  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
690  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
691  << ", sol._dual[r] = " << rationalToString(sol._dual[r])
692  << "\n" );
693  dualViolation = -sol._dual[r];
694  }
695 
696  if( ((maximizing && basisStatusRow != SPxSolver::ON_UPPER) || (!maximizing && basisStatusRow != SPxSolver::ON_LOWER))
697  && sol._dual[r] > dualViolation )
698  {
699  MSG_DEBUG( std::cout << "basisStatusRow = " << basisStatusRow
700  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
701  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
702  << ", sol._dual[r] = " << rationalToString(sol._dual[r])
703  << "\n" );
704  dualViolation = sol._dual[r];
705  }
706  }
707 
708  _modObj = sol._redCost;
709 
710  // output violations; the reduced cost violations for artificially introduced slack columns are actually violations of the dual multipliers
712  << "Max. bound violation = " << rationalToString(boundsViolation) << "\n"
713  << "Max. row violation = " << rationalToString(sideViolation) << "\n"
714  << "Max. reduced cost violation = " << rationalToString(redCostViolation) << "\n"
715  << "Max. dual violation = " << rationalToString(dualViolation) << "\n" );
716 
718  << std::fixed << std::setprecision(2) << std::setw(10)
719  << "Progress table: "
720  << std::setw(10) << _statistics->refinements << " & "
721  << std::setw(10) << _statistics->iterations << " & "
722  << std::setw(10) << _statistics->solvingTime->time() << " & "
723  << std::setw(10) << _statistics->rationalTime->time() << " & "
724  << std::setw(10) << rationalToString(boundsViolation > sideViolation ? boundsViolation : sideViolation, 2) << " & "
725  << std::setw(10) << rationalToString(redCostViolation > dualViolation ? redCostViolation : dualViolation, 2) << "\n");
726 
727  // terminate if tolerances are satisfied
728  primalFeasible = (boundsViolation <= _rationalFeastol && sideViolation <= _rationalFeastol);
729  dualFeasible = (redCostViolation <= _rationalOpttol && dualViolation <= _rationalOpttol);
730  if( primalFeasible && dualFeasible )
731  {
732  if( minRounds < 0 )
733  {
734  MSG_INFO1( spxout, spxout << "Tolerances reached.\n" );
735  break;
736  }
737  else
738  {
739  MSG_INFO1( spxout, spxout << "Tolerances reached but minRounds forcing additional refinement rounds.\n" );
740  }
741  }
742 
743  // terminate if some limit is reached
744  if( _isSolveStopped(stoppedTime, stoppedIter) )
745  break;
746 
747  // check progress
748  maxViolation = boundsViolation;
749  if( sideViolation > maxViolation )
750  maxViolation = sideViolation;
751  if( redCostViolation > maxViolation )
752  maxViolation = redCostViolation;
753  if( dualViolation > maxViolation )
754  maxViolation = dualViolation;
755  bestViolation *= violationImprovementFactor;
756  if( maxViolation > bestViolation )
757  {
758  MSG_INFO2( spxout, spxout << "Failed to reduce violation significantly.\n" );
759  numFailedRefinements++;
760  }
761  else
762  bestViolation = maxViolation;
763 
764  // decide whether to perform rational reconstruction and/or factorization
765  bool performRatfac = boolParam(SoPlex::RATFAC)
766  && lastStallRefinements >= intParam(SoPlex::RATFAC_MINSTALLS) && _hasBasis && factorSolNewBasis;
767  bool performRatrec = boolParam(SoPlex::RATREC)
768  && (_statistics->refinements >= nextRatrecRefinement || performRatfac);
769 
770  // attempt rational reconstruction
771  errorCorrection *= errorCorrectionFactor;
772  if( performRatrec && maxViolation > 0 )
773  {
774  MSG_INFO1( spxout, spxout << "Performing rational reconstruction . . .\n" );
775 
776  maxViolation *= errorCorrection; // only used for sign check later
777  maxViolation.invert();
779  {
780  MSG_INFO1( spxout, spxout << "Tolerances reached.\n" );
781  primalFeasible = true;
782  dualFeasible = true;
783  break;
784  }
785  nextRatrecRefinement = int(_statistics->refinements * realParam(SoPlex::RATREC_FREQ)) + 1;
786  MSG_DEBUG( spxout << "Next rational reconstruction after refinement " << nextRatrecRefinement << ".\n" );
787  }
788 
789  // solve basis systems exactly
790  if( performRatfac && maxViolation > 0 )
791  {
792  MSG_INFO1( spxout, spxout << "Performing rational factorization . . .\n" );
793 
794  bool optimal;
795  _factorizeColumnRational(sol, _basisStatusRows, _basisStatusCols, stoppedTime, stoppedIter, error, optimal);
796  factorSolNewBasis = false;
797 
798  if( stoppedTime )
799  {
800  MSG_INFO1( spxout, spxout << "Stopped rational factorization.\n" );
801  }
802  else if( error )
803  {
804  // message was already printed; reset error flag and continue without factorization
805  error = false;
806  }
807  else if( optimal )
808  {
809  MSG_INFO1( spxout, spxout << "Tolerances reached.\n" );
810  primalFeasible = true;
811  dualFeasible = true;
812  break;
813  }
814  else if( boolParam(SoPlex::RATFACJUMP) )
815  {
816  MSG_INFO1( spxout, spxout << "Jumping to exact basic solution.\n" );
817  minRounds++;
818  continue;
819  }
820  }
821 
822  // start refinement
823 
824  // compute primal scaling factor; limit increase in scaling by tolerance used in floating point solve
825  maxScale = primalScale;
826  maxScale *= _rationalMaxscaleincr;
827 
828  primalScale = boundsViolation > sideViolation ? boundsViolation : sideViolation;
829  if( primalScale < redCostViolation )
830  primalScale = redCostViolation;
831  assert(primalScale >= 0);
832 
833  if( primalScale > 0 )
834  {
835  primalScale.invert();
836  if( primalScale > maxScale )
837  primalScale = maxScale;
838  }
839  else
840  primalScale = maxScale;
841 
843  primalScale.powRound();
844 
845  // apply scaled bounds
846  if( primalScale <= 1 )
847  {
848  if( primalScale < 1 )
849  primalScale = 1;
850  for( int c = numColsRational() - 1; c >= 0; c-- )
851  {
852  if( _lowerFinite(_colTypes[c]) )
853  {
854  if( _modLower[c] <= _rationalNegInfty )
856  else
858  }
859  if( _upperFinite(_colTypes[c]) )
860  {
861  if( _modUpper[c] >= _rationalPosInfty )
863  else
865  }
866  }
867  }
868  else
869  {
870  MSG_INFO2( spxout, spxout << "Scaling primal by " << rationalToString(primalScale) << ".\n" );
871 
872  for( int c = numColsRational() - 1; c >= 0; c-- )
873  {
874  if( _lowerFinite(_colTypes[c]) )
875  {
876  _modLower[c] *= primalScale;
877  if( _modLower[c] <= _rationalNegInfty )
879  else
881  }
882  if( _upperFinite(_colTypes[c]) )
883  {
884  _modUpper[c] *= primalScale;
885  if( _modUpper[c] >= _rationalPosInfty )
887  else
889  }
890  }
891  }
892 
893  // apply scaled sides
894  assert(primalScale >= 1);
895  if( primalScale == 1 )
896  {
897  for( int r = numRowsRational() - 1; r >= 0; r-- )
898  {
899  if( _lowerFinite(_rowTypes[r]) )
900  {
901  if( _modLhs[r] <= _rationalNegInfty )
903  else
904  _solver.changeLhs(r, Real(_modLhs[r]));
905  }
906  if( _upperFinite(_rowTypes[r]) )
907  {
908  if( _modRhs[r] >= _rationalPosInfty )
910  else
911  _solver.changeRhs(r, Real(_modRhs[r]));
912  }
913  }
914  }
915  else
916  {
917  for( int r = numRowsRational() - 1; r >= 0; r-- )
918  {
919  if( _lowerFinite(_rowTypes[r]) )
920  {
921  _modLhs[r] *= primalScale;
922  if( _modLhs[r] <= _rationalNegInfty )
924  else
925  _solver.changeLhs(r, Real(_modLhs[r]));
926  }
927  if( _upperFinite(_rowTypes[r]) )
928  {
929  _modRhs[r] *= primalScale;
930  if( _modRhs[r] >= _rationalPosInfty )
932  else
933  _solver.changeRhs(r, Real(_modRhs[r]));
934  }
935  }
936  }
937 
938  // compute dual scaling factor; limit increase in scaling by tolerance used in floating point solve
939  maxScale = dualScale;
940  maxScale *= _rationalMaxscaleincr;
941 
942  dualScale = redCostViolation > dualViolation ? redCostViolation : dualViolation;
943  assert(dualScale >= 0);
944 
945  if( dualScale > 0 )
946  {
947  dualScale.invert();
948  if( dualScale > maxScale )
949  dualScale = maxScale;
950  }
951  else
952  dualScale = maxScale;
953 
955  dualScale.powRound();
956 
957  if( dualScale > primalScale )
958  dualScale = primalScale;
959 
960  if( dualScale < 1 )
961  dualScale = 1;
962  else
963  {
964  MSG_INFO2( spxout, spxout << "Scaling dual by " << rationalToString(dualScale) << ".\n" );
965 
966  // perform dual scaling
967  ///@todo remove _modObj and use dualScale * sol._redCost directly
968  _modObj *= dualScale;
969  }
970 
971  // apply scaled objective function
972  for( int c = numColsRational() - 1; c >= 0; c-- )
973  {
974  if( _modObj[c] >= _rationalPosInfty )
976  else if( _modObj[c] <= _rationalNegInfty )
978  else
979  _solver.changeObj(c, Real(_modObj[c]));
980  }
981  for( int r = numRowsRational() - 1; r >= 0; r-- )
982  {
983  Rational newRowObj;
984  if( _rowTypes[r] == RANGETYPE_FIXED )
985  _solver.changeRowObj(r, 0.0);
986  else
987  {
988  newRowObj = sol._dual[r];
989  newRowObj *= dualScale;
990  if( newRowObj >= _rationalPosInfty )
992  else if( newRowObj <= _rationalNegInfty )
994  else
995  _solver.changeRowObj(r, -Real(newRowObj));
996  }
997  }
998 
999  MSG_INFO1( spxout, spxout << "Refined floating-point solve . . .\n" );
1000 
1001  // ensure that artificial slack columns are basic and inequality constraints are nonbasic; otherwise we may end
1002  // up with dual violation on inequality constraints after removing the slack columns; do not change this in the
1003  // floating-point solver, though, because the solver may require its original basis to detect optimality
1004  if( _slackCols.num() > 0 && _hasBasis )
1005  {
1006  int numOrigCols = numColsRational() - _slackCols.num();
1007  assert(_slackCols.num() <= 0 || boolParam(SoPlex::EQTRANS));
1008  for( int i = 0; i < _slackCols.num(); i++ )
1009  {
1010  int row = _slackCols.colVector(i).index(0);
1011  int col = numOrigCols + i;
1012 
1013  assert(row >= 0);
1014  assert(row < numRowsRational());
1015 
1017  {
1018  _basisStatusRows[row] = _basisStatusCols[col];
1021  }
1022  }
1023  }
1024 
1025  // load basis
1027  {
1028  MSG_DEBUG( spxout << "basis (status = " << _solver.basis().status() << ") desc before set:\n"; _solver.basis().desc().dump() );
1030  MSG_DEBUG( spxout << "basis (status = " << _solver.basis().status() << ") desc after set:\n"; _solver.basis().desc().dump() );
1031 
1033  MSG_DEBUG( spxout << "setting basis in solver " << (_hasBasis ? "successful" : "failed") << " (3)\n" );
1034  }
1035 
1036  // solve modified problem
1037  int prevIterations = _statistics->iterations;
1039  result = _solveRealStable(acceptUnbounded, acceptInfeasible, primalReal, dualReal, _basisStatusRows, _basisStatusCols, _hasBasis, primalScale > 1e20 || dualScale > 1e20);
1040 
1041  // count refinements and remember whether we moved to a new basis
1043  if( _statistics->iterations <= prevIterations )
1044  {
1045  lastStallRefinements++;
1047  }
1048  else
1049  {
1050  factorSolNewBasis = true;
1051  lastStallRefinements = 0;
1053  }
1054 
1055  // evaluate result; if modified problem was not solved to optimality, stop refinement
1056  switch( result )
1057  {
1058  case SPxSolver::OPTIMAL:
1059  MSG_INFO1( spxout, spxout << "Floating-point optimal.\n" );
1060  break;
1061  case SPxSolver::INFEASIBLE:
1062  MSG_INFO1( spxout, spxout << "Floating-point infeasible.\n" );
1063  sol._dualFarkas = dualReal;
1064  sol._hasDualFarkas = true;
1065  infeasible = true;
1067  return;
1068  case SPxSolver::UNBOUNDED:
1069  MSG_INFO1( spxout, spxout << "Floating-point unbounded.\n" );
1070  unbounded = true;
1072  return;
1073  case SPxSolver::ABORT_TIME:
1074  stoppedTime = true;
1075  return;
1076  case SPxSolver::ABORT_ITER:
1077  stoppedIter = true;
1079  return;
1080  default:
1081  error = true;
1083  return;
1084  }
1085 
1087 
1088  // correct primal solution and align with basis
1089  MSG_DEBUG( std::cout << "Correcting primal solution.\n" );
1090 
1091  int primalSize = 0;
1092  Rational primalScaleInverse = primalScale;
1093  primalScaleInverse.invert();
1095  for( int c = numColsRational() - 1; c >= 0; c-- )
1096  {
1097  // force values of nonbasic variables to bounds
1098  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
1099 
1100  if( basisStatusCol == SPxSolver::ON_LOWER )
1101  {
1102  if( sol._primal[c] != lowerRational(c) )
1103  {
1104  int i = _primalDualDiff.size();
1106  _primalDualDiff.add(c);
1108  _primalDualDiff.value(i) -= sol._primal[c];
1109  sol._primal[c] = lowerRational(c);
1110  }
1111  }
1112  else if( basisStatusCol == SPxSolver::ON_UPPER )
1113  {
1114  if( sol._primal[c] != upperRational(c) )
1115  {
1116  int i = _primalDualDiff.size();
1118  _primalDualDiff.add(c);
1120  _primalDualDiff.value(i) -= sol._primal[c];
1121  sol._primal[c] = upperRational(c);
1122  }
1123  }
1124  else if( basisStatusCol == SPxSolver::FIXED )
1125  {
1126  // it may happen that lower and upper are only equal in the real LP but different in the rational LP; we
1127  // do not check this to avoid rational comparisons, but simply switch the basis status to the lower
1128  // bound; this is necessary, because for fixed variables any reduced cost is feasible
1129  basisStatusCol = SPxSolver::ON_LOWER;
1130  if( sol._primal[c] != lowerRational(c) )
1131  {
1132  int i = _primalDualDiff.size();
1134  _primalDualDiff.add(c);
1136  _primalDualDiff.value(i) -= sol._primal[c];
1137  sol._primal[c] = lowerRational(c);
1138  }
1139  }
1140  else if( basisStatusCol == SPxSolver::ZERO )
1141  {
1142  if( sol._primal[c] != 0 )
1143  {
1144  int i = _primalDualDiff.size();
1146  _primalDualDiff.add(c);
1147  _primalDualDiff.value(i) = sol._primal[c];
1148  _primalDualDiff.value(i) *= -1;
1149  sol._primal[c] = 0;
1150  }
1151  }
1152  else
1153  {
1154  if( primalReal[c] == 1.0 )
1155  {
1156  int i = _primalDualDiff.size();
1158  _primalDualDiff.add(c);
1159  _primalDualDiff.value(i) = primalScaleInverse;
1160  sol._primal[c] += _primalDualDiff.value(i);
1161  }
1162  else if( primalReal[c] == -1.0 )
1163  {
1164  int i = _primalDualDiff.size();
1166  _primalDualDiff.add(c);
1167  _primalDualDiff.value(i) = primalScaleInverse;
1168  _primalDualDiff.value(i) *= -1;
1169  sol._primal[c] += _primalDualDiff.value(i);
1170  }
1171  else if( primalReal[c] != 0.0 )
1172  {
1173  int i = _primalDualDiff.size();
1175  _primalDualDiff.add(c);
1176  _primalDualDiff.value(i) = primalReal[c];
1177  _primalDualDiff.value(i) *= primalScaleInverse;
1178  sol._primal[c] += _primalDualDiff.value(i);
1179  }
1180  }
1181 
1182  if( sol._primal[c] != 0 )
1183  primalSize++;
1184  }
1185 
1186  // update or recompute slacks depending on which looks faster
1187  if( _primalDualDiff.size() < primalSize )
1188  {
1190 #ifndef NDEBUG
1191 #ifdef SOPLEX_WITH_GMP
1192  {
1193  DVectorRational activity(numRowsRational());
1194  _rationalLP->computePrimalActivity(sol._primal, activity);
1195  assert(sol._slacks == activity);
1196  }
1197 #endif
1198 #endif
1199  }
1200  else
1202  const int numCorrectedPrimals = _primalDualDiff.size();
1203 
1204  // correct dual solution and align with basis
1205  MSG_DEBUG( std::cout << "Correcting dual solution.\n" );
1206 
1207 #ifndef NDEBUG
1208  {
1209  // compute reduced cost violation
1210  DVectorRational debugRedCost(numColsRational());
1211  debugRedCost = DVectorRational(_realLP->maxObj());
1212  debugRedCost *= -1;
1213  _rationalLP->subDualActivity(DVectorRational(dualReal), debugRedCost);
1214 
1215  Rational debugRedCostViolation = 0;
1216  for( int c = numColsRational() - 1; c >= 0; c-- )
1217  {
1218  if( _colTypes[c] == RANGETYPE_FIXED )
1219  continue;
1220 
1221  const SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
1222  assert(basisStatusCol != SPxSolver::FIXED);
1223 
1224  if( ((maximizing && basisStatusCol != SPxSolver::ON_LOWER) || (!maximizing && basisStatusCol != SPxSolver::ON_UPPER))
1225  && debugRedCost[c] < -debugRedCostViolation )
1226  {
1227  MSG_DEBUG( std::cout << "basisStatusCol = " << basisStatusCol
1228  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
1229  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
1230  << ", obj[c] = " << _realLP->obj(c)
1231  << ", debugRedCost[c] = " << rationalToString(debugRedCost[c])
1232  << "\n" );
1233  debugRedCostViolation = -debugRedCost[c];
1234  }
1235 
1236  if( ((maximizing && basisStatusCol != SPxSolver::ON_UPPER) || (!maximizing && basisStatusCol != SPxSolver::ON_LOWER))
1237  && debugRedCost[c] > debugRedCostViolation )
1238  {
1239  MSG_DEBUG( std::cout << "basisStatusCol = " << basisStatusCol
1240  << ", lower tight = " << bool(sol._primal[c] <= lowerRational(c))
1241  << ", upper tight = " << bool(sol._primal[c] >= upperRational(c))
1242  << ", obj[c] = " << _realLP->obj(c)
1243  << ", debugRedCost[c] = " << rationalToString(debugRedCost[c])
1244  << "\n" );
1245  debugRedCostViolation = debugRedCost[c];
1246  }
1247  }
1248 
1249  // compute dual violation
1250  Rational debugDualViolation = 0;
1251  Rational debugBasicDualViolation = 0;
1252  for( int r = numRowsRational() - 1; r >= 0; r-- )
1253  {
1254  if( _rowTypes[r] == RANGETYPE_FIXED )
1255  continue;
1256 
1257  const SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
1258  assert(basisStatusRow != SPxSolver::FIXED);
1259 
1260  Rational val = (-dualScale * sol._dual[r]) - Rational(dualReal[r]);
1261 
1262  if( ((maximizing && basisStatusRow != SPxSolver::ON_LOWER) || (!maximizing && basisStatusRow != SPxSolver::ON_UPPER))
1263  && val > debugDualViolation )
1264  {
1265  MSG_DEBUG( std::cout << "basisStatusRow = " << basisStatusRow
1266  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1267  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1268  << ", dualReal[r] = " << rationalToString(val)
1269  << ", dualReal[r] = " << dualReal[r]
1270  << "\n" );
1271  debugDualViolation = val;
1272  }
1273 
1274  if( ((maximizing && basisStatusRow != SPxSolver::ON_UPPER) || (!maximizing && basisStatusRow != SPxSolver::ON_LOWER))
1275  && val < -debugDualViolation )
1276  {
1277  MSG_DEBUG( std::cout << "basisStatusRow = " << basisStatusRow
1278  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1279  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1280  << ", dualReal[r] = " << rationalToString(val)
1281  << ", dualReal[r] = " << dualReal[r]
1282  << "\n" );
1283  debugDualViolation = -val;
1284  }
1285 
1286  if( basisStatusRow == SPxSolver::BASIC && spxAbs(val) > debugBasicDualViolation )
1287  {
1288  MSG_DEBUG( std::cout << "basisStatusRow = " << basisStatusRow
1289  << ", lower tight = " << bool(sol._slacks[r] <= lhsRational(r))
1290  << ", upper tight = " << bool(sol._slacks[r] >= rhsRational(r))
1291  << ", dualReal[r] = " << rationalToString(val)
1292  << ", dualReal[r] = " << dualReal[r]
1293  << "\n" );
1294  debugBasicDualViolation = spxAbs(val);
1295  }
1296  }
1297 
1298  if( debugRedCostViolation > _solver.opttol() || debugDualViolation > _solver.opttol() || debugBasicDualViolation > 1e-9 )
1299  {
1300  MSG_WARNING( spxout, spxout << "Warning: floating-point dual solution with violation "
1301  << rationalToString(debugRedCostViolation) << " / "
1302  << rationalToString(debugDualViolation) << " / "
1303  << rationalToString(debugBasicDualViolation)
1304  << " (red. cost, dual, basic).\n" );
1305  }
1306  }
1307 #endif
1308 
1309  Rational dualScaleInverseNeg = dualScale;
1310  dualScaleInverseNeg.invert();
1311  dualScaleInverseNeg *= -1;
1313  dualSize = 0;
1314  for( int r = numRowsRational() - 1; r >= 0; r-- )
1315  {
1316  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
1317 
1318  // it may happen that left-hand and right-hand side are different in the rational, but equal in the real LP,
1319  // leading to a fixed basis status; this is critical because rows with fixed basis status are ignored in the
1320  // computation of the dual violation; to avoid rational comparisons we do not check this but simply switch
1321  // to the left-hand side status
1322  if( basisStatusRow == SPxSolver::FIXED )
1323  basisStatusRow = SPxSolver::ON_LOWER;
1324 
1325  {
1326  if( dualReal[r] != 0 )
1327  {
1328  int i = _primalDualDiff.size();
1330  _primalDualDiff.add(r);
1331  _primalDualDiff.value(i) = dualReal[r];
1332  _primalDualDiff.value(i) *= dualScaleInverseNeg;
1333  sol._dual[r] -= _primalDualDiff.value(i);
1334 
1335  dualSize++;
1336  }
1337  else
1338  {
1339  // we do not check whether the dual value is nonzero, because it probably is; this gives us an
1340  // overestimation of the number of nonzeros in the dual solution
1341  dualSize++;
1342  }
1343  }
1344  }
1345 
1346  // update or recompute reduced cost values depending on which looks faster; adding one to the length of the
1347  // dual vector accounts for the objective function vector
1348  if( _primalDualDiff.size() < dualSize + 1 )
1349  {
1351 #ifndef NDEBUG
1352  {
1353  DVectorRational activity(_rationalLP->maxObj());
1354  activity *= -1;
1355  _rationalLP->subDualActivity(sol._dual, activity);
1356  }
1357 #endif
1358  }
1359  else
1360  {
1361  // we assume that the objective function vector has less nonzeros than the reduced cost vector, and so multiplying
1362  // with -1 first and subtracting the dual activity should be faster than adding the dual activity and negating
1363  // afterwards
1364  _rationalLP->getObj(sol._redCost);
1366  }
1367  const int numCorrectedDuals = _primalDualDiff.size();
1368 
1369  if( numCorrectedPrimals + numCorrectedDuals > 0 )
1370  {
1371  MSG_INFO2( spxout, spxout << "Corrected " << numCorrectedPrimals << " primal variables and " << numCorrectedDuals << " dual values.\n" );
1372  }
1373  }
1374  while( true );
1375 
1376  // correct basis status for restricted inequalities
1377  if( _hasBasis )
1378  {
1379  for( int r = numRowsRational() - 1; r >= 0; r-- )
1380  {
1381  assert((lhsRational(r) == rhsRational(r)) == (_rowTypes[r] == RANGETYPE_FIXED));
1383  _basisStatusRows[r] = (maximizing == (sol._dual[r] < 0))
1386  }
1387  }
1388 
1389  // compute objective function values
1390  assert(sol._isPrimalFeasible == sol._isDualFeasible);
1391  if( sol._isPrimalFeasible)
1392  {
1393  sol._objVal = sol._primal * _rationalLP->maxObj();
1395  sol._objVal *= -1;
1396  }
1397 
1398  // set objective coefficients for all rows to zero
1400 
1401  // stop rational solving time
1403  }
1404 
1405 
1406 
1407  /// performs iterative refinement on the auxiliary problem for testing unboundedness
1409  SolRational& sol,
1410  bool& hasUnboundedRay,
1411  bool& stopped,
1412  bool& stoppedIter,
1413  bool& error)
1414  {
1415  bool primalFeasible;
1416  bool dualFeasible;
1417  bool infeasible;
1418  bool unbounded;
1419 
1420  // move objective function to constraints and adjust sides and bounds
1422 
1423  // invalidate solution
1424  sol.invalidate();
1425 
1426  // remember current number of refinements
1427  int oldRefinements = _statistics->refinements;
1428 
1429  // perform iterative refinement
1430  _performOptIRStable(sol, false, false, 0, primalFeasible, dualFeasible, infeasible, unbounded, stopped, stoppedIter, error);
1431 
1432  // update unbounded refinement counter
1433  _statistics->unbdRefinements += _statistics->refinements - oldRefinements;
1434 
1435  // stopped due to some limit
1436  if( stopped )
1437  {
1438  sol.invalidate();
1439  hasUnboundedRay = false;
1440  error = false;
1441  }
1442  // the unbounded problem should always be solved to optimality
1443  else if( error || unbounded || infeasible || !primalFeasible || !dualFeasible )
1444  {
1445  sol.invalidate();
1446  hasUnboundedRay = false;
1447  stopped = false;
1448  error = true;
1449  }
1450  else
1451  {
1452  const Rational& tau = sol._primal[numColsRational() - 1];
1453 
1454  MSG_DEBUG( std::cout << "tau = " << tau << " (roughly " << rationalToString(tau) << ")\n" );
1455 
1456  assert(tau <= 1.0 + 2.0 * realParam(SoPlex::FEASTOL));
1457  assert(tau >= -realParam(SoPlex::FEASTOL));
1458 
1459  // because the right-hand side and all bounds (but tau's upper bound) are zero, tau should be approximately
1460  // zero if basic; otherwise at its upper bound 1
1461  error = !(tau >= _rationalPosone || tau <= _rationalFeastol);
1462  assert(!error);
1463 
1464  hasUnboundedRay = (tau >= 1);
1465  }
1466 
1467  // restore problem
1468  _untransformUnbounded(sol, hasUnboundedRay);
1469  }
1470 
1471 
1472 
1473  /// performs iterative refinement on the auxiliary problem for testing feasibility
1475  SolRational& sol,
1476  bool& withDualFarkas,
1477  bool& stopped,
1478  bool& stoppedIter,
1479  bool& error)
1480  {
1481  bool primalFeasible;
1482  bool dualFeasible;
1483  bool infeasible;
1484  bool unbounded;
1485  bool success = false;
1486  error = false;
1487 
1488 #if 0
1489  // if the problem has been found to be infeasible and an approximate Farkas proof is available, we compute a
1490  // scaled unit box around the origin that provably contains no feasible solution; this currently only works for
1491  // equality form
1492  ///@todo check whether approximate Farkas proof can be used
1494  ///@todo if approx Farkas proof is good enough then exit without doing any transformation
1495 #endif
1496 
1497  // remove objective function, shift, homogenize
1499 
1500  // invalidate solution
1501  sol.invalidate();
1502 
1503  do
1504  {
1505  // remember current number of refinements
1506  int oldRefinements = _statistics->refinements;
1507 
1508  // perform iterative refinement
1509  _performOptIRStable(sol, false, false, 0, primalFeasible, dualFeasible, infeasible, unbounded, stopped, stoppedIter, error);
1510 
1511  // update feasible refinement counter
1512  _statistics->feasRefinements += _statistics->refinements - oldRefinements;
1513 
1514  // stopped due to some limit
1515  if( stopped )
1516  {
1517  sol.invalidate();
1518  withDualFarkas = false;
1519  error = false;
1520  }
1521  // the feasibility problem should always be solved to optimality
1522  else if( error || unbounded || infeasible || !primalFeasible || !dualFeasible )
1523  {
1524  sol.invalidate();
1525  withDualFarkas = false;
1526  stopped = false;
1527  error = true;
1528  }
1529  // else we should have either a refined Farkas proof or an approximate feasible solution to the original
1530  else
1531  {
1532  const Rational& tau = sol._primal[numColsRational() - 1];
1533 
1534  MSG_DEBUG( std::cout << "tau = " << tau << " (roughly " << rationalToString(tau) << ")\n" );
1535 
1536  assert(tau >= -realParam(SoPlex::FEASTOL));
1537  assert(tau <= 1.0 + realParam(SoPlex::FEASTOL));
1538 
1539  error = (tau < -_rationalFeastol || tau > _rationalPosone + _rationalFeastol);
1540  withDualFarkas = (tau < _rationalPosone);
1541 
1542  if( withDualFarkas )
1543  {
1546 
1547 #if 0
1548  // check if we can compute sufficiently large Farkas box
1550 #endif
1551  if( true )//@todo check if computeInfeasBox found a sufficient box
1552  {
1553 
1554  success = true;
1555  sol._isPrimalFeasible= false;
1556  }
1557  }
1558  else
1559  {
1560  sol._isDualFeasible = false;
1561  success = true; //successfully found approximate feasible solution
1562  }
1563  }
1564  }
1565  while(!error && !success && !stopped);
1566 
1567  // restore problem
1568  _untransformFeasibility(sol, withDualFarkas);
1569  }
1570 
1571 
1572 
1573  /// reduces matrix coefficient in absolute value by the lifting procedure of Thiele et al. 2013
1575  {
1576  MSG_DEBUG( std::cout << "Reducing matrix coefficients by lifting.\n" );
1577 
1578  // start timing
1580 
1581  MSG_DEBUG( _realLP->writeFile("beforeLift.lp", 0, 0, 0) );
1582 
1583  // remember unlifted state
1586 
1587  // allocate vector memory
1588  DSVectorRational colVector;
1589  SVectorRational::Element liftingRowMem[2];
1590  SVectorRational liftingRowVector(2, liftingRowMem);
1591 
1592  // search each column for large nonzeros entries
1593  const Rational maxValue = realParam(SoPlex::LIFTMAXVAL);
1594 
1595  for( int i = 0; i < numColsRational(); i++ )
1596  {
1597  MSG_DEBUG( std::cout << "in lifting: examining column " << i << "\n" );
1598 
1599  // get column vector
1600  colVector = colVectorRational(i);
1601 
1602  bool addedLiftingRow = false;
1603  int liftingColumnIndex = -1;
1604 
1605  // go through nonzero entries of the column
1606  for( int k = colVector.size() - 1; k >= 0; k-- )
1607  {
1608  const Rational& value = colVector.value(k);
1609 
1610  if( spxAbs(value) > maxValue )
1611  {
1612  MSG_DEBUG( std::cout << " --> nonzero " << k << " has value " << rationalToString(value) << " in row " << colVector.index(k) << "\n" );
1613 
1614  // add new column equal to maxValue times original column
1615  if( !addedLiftingRow )
1616  {
1617  MSG_DEBUG( std::cout << " --> adding lifting row\n" );
1618 
1619  assert(liftingRowVector.size() == 0);
1620 
1621  liftingColumnIndex = numColsRational();
1622  liftingRowVector.add(i, maxValue);
1623  liftingRowVector.add(liftingColumnIndex, -1);
1624 
1625  _rationalLP->addRow(LPRowRational(0, liftingRowVector, 0));
1626  _realLP->addRow(LPRowReal(0.0, DSVectorReal(liftingRowVector), 0.0));
1627 
1628  assert(liftingColumnIndex == numColsRational() - 1);
1629  assert(liftingColumnIndex == numColsReal() - 1);
1630 
1633 
1634  liftingRowVector.clear();
1635  addedLiftingRow = true;
1636  }
1637 
1638  // get row index
1639  int rowIndex = colVector.index(k);
1640  assert(rowIndex >= 0);
1641  assert(rowIndex < _beforeLiftRows);
1642  assert(liftingColumnIndex == numColsRational() - 1);
1643 
1644  MSG_DEBUG( std::cout << " --> changing matrix\n" );
1645 
1646  // remove nonzero from original column
1647  _rationalLP->changeElement(rowIndex, i, 0);
1648  _realLP->changeElement(rowIndex, i, 0.0);
1649 
1650  // add nonzero divided by maxValue to new column
1651  Rational newValue(value);
1652  newValue /= maxValue;
1653  _rationalLP->changeElement(rowIndex, liftingColumnIndex, newValue);
1654  _realLP->changeElement(rowIndex, liftingColumnIndex, Real(newValue));
1655  }
1656  }
1657  }
1658 
1659  // search each column for small nonzeros entries
1660  const Rational minValue = realParam(SoPlex::LIFTMINVAL);
1661 
1662  for( int i = 0; i < numColsRational(); i++ )
1663  {
1664  MSG_DEBUG( std::cout << "in lifting: examining column " << i << "\n" );
1665 
1666  // get column vector
1667  colVector = colVectorRational(i);
1668 
1669  bool addedLiftingRow = false;
1670  int liftingColumnIndex = -1;
1671 
1672  // go through nonzero entries of the column
1673  for( int k = colVector.size() - 1; k >= 0; k-- )
1674  {
1675  const Rational& value = colVector.value(k);
1676 
1677  if( spxAbs(value) < minValue )
1678  {
1679  MSG_DEBUG( std::cout << " --> nonzero " << k << " has value " << rationalToString(value) << " in row " << colVector.index(k) << "\n" );
1680 
1681  // add new column equal to maxValue times original column
1682  if( !addedLiftingRow )
1683  {
1684  MSG_DEBUG( std::cout << " --> adding lifting row\n" );
1685 
1686  assert(liftingRowVector.size() == 0);
1687 
1688  liftingColumnIndex = numColsRational();
1689  liftingRowVector.add(i, minValue);
1690  liftingRowVector.add(liftingColumnIndex, -1);
1691 
1692  _rationalLP->addRow(LPRowRational(0, liftingRowVector, 0));
1693  _realLP->addRow(LPRowReal(0.0, DSVectorReal(liftingRowVector), 0.0));
1694 
1695  assert(liftingColumnIndex == numColsRational() - 1);
1696  assert(liftingColumnIndex == numColsReal() - 1);
1697 
1700 
1701  liftingRowVector.clear();
1702  addedLiftingRow = true;
1703  }
1704 
1705  // get row index
1706  int rowIndex = colVector.index(k);
1707  assert(rowIndex >= 0);
1708  assert(rowIndex < _beforeLiftRows);
1709  assert(liftingColumnIndex == numColsRational() - 1);
1710 
1711  MSG_DEBUG( std::cout << " --> changing matrix\n" );
1712 
1713  // remove nonzero from original column
1714  _rationalLP->changeElement(rowIndex, i, 0);
1715  _realLP->changeElement(rowIndex, i, 0.0);
1716 
1717  // add nonzero divided by maxValue to new column
1718  Rational newValue(value);
1719  newValue /= minValue;
1720  _rationalLP->changeElement(rowIndex, liftingColumnIndex, newValue);
1721  _realLP->changeElement(rowIndex, liftingColumnIndex, Real(newValue));
1722  }
1723  }
1724  }
1725 
1726  // adjust basis
1727  if( _hasBasis )
1728  {
1729  assert(numColsRational() >= _beforeLiftCols);
1730  assert(numRowsRational() >= _beforeLiftRows);
1731 
1735  }
1736 
1737  MSG_DEBUG( _realLP->writeFile("afterLift.lp", 0, 0, 0) );
1738 
1739  // stop timing
1741 
1742  if( numColsRational() > _beforeLiftCols || numRowsRational() > _beforeLiftRows )
1743  {
1744  MSG_INFO1( spxout, spxout << "Added " << numColsRational() - _beforeLiftCols << " columns and "
1745  << numRowsRational() - _beforeLiftRows << " rows to reduce large matrix coefficients\n." );
1746  }
1747  }
1748 
1749 
1750 
1751  /// undoes lifting
1753  {
1754  // start timing
1756 
1757  // print LP if in debug mode
1758  MSG_DEBUG( _realLP->writeFile("beforeProject.lp", 0, 0, 0) );
1759 
1760  assert(numColsRational() >= _beforeLiftCols);
1761  assert(numRowsRational() >= _beforeLiftRows);
1762 
1763  // shrink rational LP to original size
1766 
1767  // shrink real LP to original size
1770 
1771  // adjust solution
1772  if( sol.isPrimalFeasible() )
1773  {
1776  }
1777 
1778  if( sol.hasPrimalRay() )
1779  {
1781  }
1782 
1783  ///@todo if we know the mapping between original and lifting columns, we simply need to add the reduced cost of
1784  /// the lifting column to the reduced cost of the original column; this is not implemented now, because for
1785  /// optimal solutions the reduced costs of the lifting columns are zero
1786  const Rational maxValue = realParam(SoPlex::LIFTMAXVAL);
1787 
1788  for( int i = _beforeLiftCols; i < numColsRational() && sol._isDualFeasible; i++ )
1789  {
1790  if( spxAbs(maxValue * sol._redCost[i]) > _rationalOpttol )
1791  {
1792  MSG_INFO1( spxout, spxout << "Warning: lost dual solution during project phase.\n" );
1793  sol._isDualFeasible = false;
1794  }
1795  }
1796 
1797  if( sol.isDualFeasible() )
1798  {
1801  }
1802 
1803  if( sol.hasDualFarkas() )
1804  {
1806  }
1807 
1808  // adjust basis
1809  for( int i = _beforeLiftCols; i < numColsRational() && _hasBasis; i++ )
1810  {
1812  {
1813  MSG_INFO1( spxout, spxout << "Warning: lost basis during project phase because of nonbasic lifting column.\n" );
1814  _hasBasis = false;
1816  }
1817  }
1818 
1819  for( int i = _beforeLiftRows; i < numRowsRational() && _hasBasis; i++ )
1820  {
1822  {
1823  MSG_INFO1( spxout, spxout << "Warning: lost basis during project phase because of basic lifting row.\n" );
1824  _hasBasis = false;
1826  }
1827  }
1828 
1829  if( _hasBasis )
1830  {
1834  }
1835 
1836  // print LP if in debug mode
1837  MSG_DEBUG( _realLP->writeFile("afterProject.lp", 0, 0, 0) );
1838 
1839  // stop timing
1841  }
1842 
1843 
1844 
1845  /// stores objective, bounds, and sides of real LP
1847  {
1848 #ifndef SOPLEX_MANUAL_ALT
1850  {
1852  return;
1853  }
1854 #endif
1855 
1856  _manualLower = _realLP->lower();
1857  _manualUpper = _realLP->upper();
1858  _manualLhs = _realLP->lhs();
1859  _manualRhs = _realLP->rhs();
1862  }
1863 
1864 
1865 
1866  /// restores objective, bounds, and sides of real LP
1868  {
1870  {
1871 #ifndef SOPLEX_MANUAL_ALT
1873 #else
1879 #endif
1880 
1881  if( _hasBasis )
1882  {
1883  // in manual sync mode, if the right-hand side of an equality constraint is not floating-point
1884  // representable, the user might have constructed the constraint in the real LP by rounding down the
1885  // left-hand side and rounding up the right-hand side; if the basis status is fixed, we need to adjust it
1886  for( int i = 0; i < _solver.nRows(); i++ )
1887  {
1888  if( _basisStatusRows[i] == SPxSolver::FIXED && _solver.lhs(i) != _solver.rhs(i) )
1889  {
1890  assert(_solver.rhs(i) == spxNextafter(_solver.lhs(i), infinity));
1894  {
1896  }
1897  else
1898  {
1900  }
1901  }
1902  }
1903 
1906  }
1907  }
1908  else
1909  {
1915  }
1916  }
1917 
1918 
1919 
1920  /// introduces slack variables to transform inequality constraints into equations for both rational and real LP,
1921  /// which should be in sync
1923  {
1924  MSG_DEBUG( std::cout << "Transforming rows to equation form.\n" );
1925 
1926  // start timing
1928 
1929  MSG_DEBUG( _realLP->writeFile("beforeTransEqu.lp", 0, 0, 0) );
1930 
1931  // clear array of slack columns
1932  _slackCols.clear();
1933 
1934  // add artificial slack variables to convert inequality to equality constraints
1935  for( int i = 0; i < numRowsRational(); i++ )
1936  {
1937  assert((lhsRational(i) == rhsRational(i)) == (_rowTypes[i] == RANGETYPE_FIXED));
1938  if( _rowTypes[i] != RANGETYPE_FIXED )
1939  {
1941  if( _rationalLP->lhs(i) != 0 )
1943  if( _rationalLP->rhs(i) != 0 )
1945  assert(_rationalLP->lhs(i) == 0);
1946  assert(_rationalLP->rhs(i) == 0);
1947  _realLP->changeRange(i, 0.0, 0.0);
1950  }
1951  }
1952 
1955 
1956  // adjust basis
1957  if( _hasBasis )
1958  {
1959  for( int i = 0; i < _slackCols.num(); i++ )
1960  {
1961  int row = _slackCols.colVector(i).index(0);
1962 
1963  assert(row >= 0);
1964  assert(row < numRowsRational());
1965 
1966  switch( _basisStatusRows[row] )
1967  {
1968  case SPxSolver::ON_LOWER:
1970  break;
1971  case SPxSolver::ON_UPPER:
1973  break;
1974  case SPxSolver::BASIC:
1975  case SPxSolver::FIXED:
1976  default:
1978  break;
1979  }
1980 
1982  }
1983 
1985  }
1986 
1987  MSG_DEBUG( _realLP->writeFile("afterTransEqu.lp", 0, 0, 0) );
1988 
1989  // stop timing
1991 
1992  if( _slackCols.num() > 0 )
1993  {
1994  MSG_INFO1( spxout, spxout << "Added " << _slackCols.num() << " slack columns to transform rows to equality form.\n" );
1995  }
1996  }
1997 
1998 
1999 
2000  /// restores original problem
2002  {
2003  // start timing
2005 
2006  // print LP if in debug mode
2007  MSG_DEBUG( _realLP->writeFile("beforeUntransEqu.lp", 0, 0, 0) );
2008 
2009  int numCols = numColsRational();
2010  int numOrigCols = numColsRational() - _slackCols.num();
2011 
2012  // adjust solution
2013  if( sol.isPrimalFeasible() )
2014  {
2015  for( int i = 0; i < _slackCols.num(); i++ )
2016  {
2017  int col = numOrigCols + i;
2018  int row = _slackCols.colVector(i).index(0);
2019 
2020  assert(row >= 0);
2021  assert(row < numRowsRational());
2022 
2023  sol._slacks[row] -= sol._primal[col];
2024  }
2025 
2026  sol._primal.reDim(numOrigCols);
2027  }
2028 
2029  if( sol.hasPrimalRay() )
2030  {
2031  sol._primalRay.reDim(numOrigCols);
2032  }
2033 
2034  // adjust basis
2035  if( _hasBasis )
2036  {
2037  for( int i = 0; i < _slackCols.num(); i++ )
2038  {
2039  int col = numOrigCols + i;
2040  int row = _slackCols.colVector(i).index(0);
2041 
2042  assert(row >= 0);
2043  assert(row < numRowsRational());
2044  assert(_basisStatusRows[row] != SPxSolver::UNDEFINED);
2045  assert(_basisStatusRows[row] != SPxSolver::ZERO || lhsRational(row) == 0);
2046  assert(_basisStatusRows[row] != SPxSolver::ZERO || rhsRational(row) == 0);
2048 
2049  MSG_DEBUG( std::cout << "slack column " << col << " for row " << row
2050  << ": col status=" << _basisStatusCols[col]
2051  << ", row status=" << _basisStatusRows[row]
2052  << ", redcost=" << rationalToString(sol._redCost[col])
2053  << ", dual=" << rationalToString(sol._dual[row]) << "\n" );
2054 
2055  if( _basisStatusRows[row] != SPxSolver::BASIC )
2056  {
2057  switch( _basisStatusCols[col] )
2058  {
2059  case SPxSolver::ON_LOWER:
2061  break;
2062  case SPxSolver::ON_UPPER:
2064  break;
2065  case SPxSolver::BASIC:
2066  case SPxSolver::FIXED:
2067  default:
2068  _basisStatusRows[row] = _basisStatusCols[col];
2069  break;
2070  }
2071  }
2072  }
2073 
2074  _basisStatusCols.reSize(numOrigCols);
2075  if( _slackCols.num() > 0 )
2077  }
2078 
2079  // not earlier because of debug message
2080  if( sol.isDualFeasible() )
2081  {
2082  sol._redCost.reDim(numOrigCols);
2083  }
2084 
2085  // restore sides and remove slack columns
2086  for( int i = 0; i < _slackCols.num(); i++ )
2087  {
2088  int col = numOrigCols + i;
2089  int row = _slackCols.colVector(i).index(0);
2090 
2091  if( upperRational(col) != 0 )
2092  _rationalLP->changeLhs(row, -upperRational(col));
2093  if( lowerRational(col) != 0 )
2094  _rationalLP->changeRhs(row, -lowerRational(col));
2095  assert(_rationalLP->lhs(row) == -upperRational(col));
2096  assert(_rationalLP->rhs(row) == -lowerRational(col));
2097  _rowTypes[row] = _switchRangeType(_colTypes[col]);
2098  }
2099 
2100  _rationalLP->removeColRange(numOrigCols, numCols - 1);
2101  _realLP->removeColRange(numOrigCols, numCols - 1);
2102  _colTypes.reSize(numOrigCols);
2103 
2104  // objective, bounds, and sides of real LP are restored only after _solveRational()
2105 
2106  // print LP if in debug mode
2107  MSG_DEBUG( _realLP->writeFile("afterUntransEqu.lp", 0, 0, 0) );
2108 
2109  // stop timing
2111  }
2112 
2113 
2114 
2115  /// transforms LP to unboundedness problem by moving the objective function to the constraints, changing right-hand
2116  /// side and bounds to zero, and adding an auxiliary variable for the decrease in the objective function
2118  {
2119  MSG_INFO1( spxout, spxout << "Setting up LP to compute primal unbounded ray.\n" );
2120 
2121  // start timing
2123 
2124  // print LP if in debug mode
2125  MSG_DEBUG( _realLP->writeFile("beforeTransUnbounded.lp", 0, 0, 0) );
2126 
2127  // store bounds
2130  for( int c = numColsRational() - 1; c >= 0; c-- )
2131  {
2132  if( _lowerFinite(_colTypes[c]) )
2134  if( _upperFinite(_colTypes[c]) )
2136  }
2137 
2138  // store sides
2141  for( int r = numRowsRational() - 1; r >= 0; r-- )
2142  {
2143  if( _lowerFinite(_rowTypes[r]) )
2144  _unboundedLhs[r] = lhsRational(r);
2145  if( _upperFinite(_rowTypes[r]) )
2146  _unboundedRhs[r] = rhsRational(r);
2147  }
2148 
2149  // make right-hand side zero
2150  for( int r = numRowsRational() - 1; r >= 0; r-- )
2151  {
2152  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2153  if( _lowerFinite(_rowTypes[r]) )
2154  {
2155  _rationalLP->changeLhs(r, 0);
2156  _realLP->changeLhs(r, 0.0);
2157  }
2158  else if( _realLP->lhs(r) > -realParam(SoPlex::INFTY) )
2160 
2161  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2162  if( _upperFinite(_rowTypes[r]) )
2163  {
2164  _rationalLP->changeRhs(r, 0);
2165  _realLP->changeRhs(r, 0.0);
2166  }
2167  else if( _realLP->rhs(r) < realParam(SoPlex::INFTY) )
2169  }
2170 
2171  // transform objective function to constraint and add auxiliary variable
2172  int numOrigCols = numColsRational();
2173  DSVectorRational obj(numOrigCols + 1);
2174  ///@todo implement this without copying the objective function
2175  obj = _rationalLP->maxObj();
2176  obj.add(numOrigCols, -1);
2177  _rationalLP->addRow(LPRowRational(0, obj, 0));
2178  _realLP->addRow(LPRowReal(0, DSVectorReal(obj), 0));
2180 
2181  assert(numColsRational() == numOrigCols + 1);
2182 
2183  // set objective coefficient and bounds for auxiliary variable
2184  _rationalLP->changeMaxObj(numOrigCols, 1);
2185  _realLP->changeMaxObj(numOrigCols, 1.0);
2186 
2187  _rationalLP->changeBounds(numOrigCols, _rationalNegInfty, 1);
2188  _realLP->changeBounds(numOrigCols, -realParam(SoPlex::INFTY), 1.0);
2190 
2191  // set objective coefficients to zero and adjust bounds for problem variables
2192  for( int c = numColsRational() - 2; c >= 0; c-- )
2193  {
2194  _rationalLP->changeObj(c, 0);
2195  _realLP->changeObj(c, 0.0);
2196 
2197  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2198  if( _lowerFinite(_colTypes[c]) )
2199  {
2200  _rationalLP->changeLower(c, 0);
2201  _realLP->changeLower(c, 0.0);
2202  }
2203  else if( _realLP->lower(c) > -realParam(SoPlex::INFTY) )
2205 
2206  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2207  if( _upperFinite(_colTypes[c]) )
2208  {
2209  _rationalLP->changeUpper(c, 0);
2210  _realLP->changeUpper(c, 0.0);
2211  }
2212  else if( _realLP->upper(c) < realParam(SoPlex::INFTY) )
2214  }
2215 
2216  // adjust basis
2217  if( _hasBasis )
2218  {
2222  }
2223 
2224  // print LP if in debug mode
2225  MSG_DEBUG( _realLP->writeFile("afterTransUnbounded.lp", 0, 0, 0) );
2226 
2227  // stop timing
2229  }
2230 
2231 
2232 
2233  /// undoes transformation to unboundedness problem
2234  void SoPlex::_untransformUnbounded(SolRational& sol, bool unbounded)
2235  {
2236  // start timing
2238 
2239  // print LP if in debug mode
2240  MSG_DEBUG( _realLP->writeFile("beforeUntransUnbounded.lp", 0, 0, 0) );
2241 
2242  int numOrigCols = numColsRational() - 1;
2243  int numOrigRows = numRowsRational() - 1;
2244  const Rational& tau = sol._primal[numOrigCols];
2245 
2246  // adjust solution and basis
2247  if( unbounded )
2248  {
2249  assert(tau >= _rationalPosone);
2250 
2251  sol._isPrimalFeasible= false;
2252  sol._hasPrimalRay = true;
2253  sol._isDualFeasible = false;
2254  sol._hasDualFarkas = false;
2255 
2256  if( tau != 1 )
2257  sol._primal /= tau;
2258 
2259  sol._primalRay = sol._primal;
2260  sol._primalRay.reDim(numOrigCols);
2261 
2262  _hasBasis = (_basisStatusCols[numOrigCols] != SPxSolver::BASIC && _basisStatusRows[numOrigRows] == SPxSolver::BASIC);
2263  _basisStatusCols.reSize(numOrigCols);
2264  _basisStatusRows.reSize(numOrigRows);
2265  }
2266  else if( boolParam(SoPlex::TESTDUALINF) && tau < _rationalFeastol )
2267  {
2268  const Rational& alpha = sol._dual[numOrigRows];
2269 
2270  assert(sol._isDualFeasible);
2271  assert(alpha <= _rationalFeastol - _rationalPosone);
2272 
2273  sol._isPrimalFeasible= false;
2274  sol._hasPrimalRay = false;
2275  sol._hasDualFarkas = false;
2276 
2277  if( alpha != -1 )
2278  {
2279  sol._dual /= -alpha;
2280  sol._redCost /= -alpha;
2281  }
2282  sol._dual.reDim(numOrigRows);
2283  sol._redCost.reDim(numOrigCols);
2284  }
2285  else
2286  {
2287  sol.invalidate();
2288  _hasBasis = false;
2289  _basisStatusCols.reSize(numOrigCols);
2290  _basisStatusCols.reSize(numOrigRows);
2291  }
2292 
2293  // recover objective function
2294  const SVectorRational& objRowVector = _rationalLP->rowVector(numOrigRows);
2295  for( int i = objRowVector.size() - 1; i >= 0; i-- )
2296  {
2297  _rationalLP->changeMaxObj(objRowVector.index(i), objRowVector.value(i));
2298  _realLP->changeMaxObj(objRowVector.index(i), Real(objRowVector.value(i)));
2299  }
2300 
2301  // remove objective function constraint and auxiliary variable
2302  _rationalLP->removeRow(numOrigRows);
2303  _realLP->removeRow(numOrigRows);
2304  _rowTypes.reSize(numOrigRows);
2305 
2306  _rationalLP->removeCol(numOrigCols);
2307  _realLP->removeCol(numOrigCols);
2308  _colTypes.reSize(numOrigCols);
2309 
2310  // restore objective, sides and bounds
2311  for( int r = numRowsRational() - 1; r >= 0; r-- )
2312  {
2313  if( _lowerFinite(_rowTypes[r]) )
2314  {
2317  }
2318  if( _upperFinite(_rowTypes[r]) )
2319  {
2322  }
2323  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2324  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2325  assert((lhsReal(r) > -realParam(SoPlex::INFTY)) == _lowerFinite(_rowTypes[r]));
2326  assert((rhsReal(r) < realParam(SoPlex::INFTY)) == _upperFinite(_rowTypes[r]));
2327  }
2328  for( int c = numColsRational() - 1; c >= 0; c-- )
2329  {
2330  if( _lowerFinite(_colTypes[c]) )
2331  {
2334  }
2335  if( _upperFinite(_colTypes[c]) )
2336  {
2339  }
2340  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2341  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2342  assert((lowerReal(c) > -realParam(SoPlex::INFTY)) == _lowerFinite(_colTypes[c]));
2343  assert((upperReal(c) < realParam(SoPlex::INFTY)) == _upperFinite(_colTypes[c]));
2344  }
2345 
2346  // invalidate rational basis factorization
2348 
2349  // print LP if in debug mode
2350  MSG_DEBUG( _realLP->writeFile("afterUntransUnbounded.lp", 0, 0, 0) );
2351 
2352  // stop timing
2354  }
2355 
2356 
2357 
2358  /// store basis
2360  {
2361  assert(!_storedBasis);
2362 
2363  if( _hasBasis )
2364  {
2365  _storedBasis = true;
2368  }
2369  else
2370  _storedBasis = false;
2371  }
2372 
2373 
2374 
2375  /// restore basis
2377  {
2378  if( _storedBasis )
2379  {
2380  _hasBasis = true;
2383  _storedBasis = false;
2384  }
2385  }
2386 
2387 
2388 
2389  /// transforms LP to feasibility problem by removing the objective function, shifting variables, and homogenizing the
2390  /// right-hand side
2392  {
2393  MSG_INFO1( spxout, spxout << "Setting up LP to test for feasibility.\n" );
2394 
2395  // start timing
2397 
2398  // print LP if in debug mode
2399  MSG_DEBUG( _realLP->writeFile("beforeTransFeas.lp", 0, 0, 0) );
2400 
2401  // store objective function
2403  for( int c = numColsRational() - 1; c >= 0; c-- )
2404  _feasObj[c] = _rationalLP->maxObj(c);
2405 
2406  // store bounds
2409  for( int c = numColsRational() - 1; c >= 0; c-- )
2410  {
2411  if( _lowerFinite(_colTypes[c]) )
2412  _feasLower[c] = lowerRational(c);
2413  if( _upperFinite(_colTypes[c]) )
2414  _feasUpper[c] = upperRational(c);
2415  }
2416 
2417  // store sides
2420  for( int r = numRowsRational() - 1; r >= 0; r-- )
2421  {
2422  if( _lowerFinite(_rowTypes[r]) )
2423  _feasLhs[r] = lhsRational(r);
2424  if( _upperFinite(_rowTypes[r]) )
2425  _feasRhs[r] = rhsRational(r);
2426  }
2427 
2428  // set objective coefficients to zero; shift primal space such as to guarantee that the zero solution is within
2429  // the bounds
2430  Rational shiftValue;
2431  Rational shiftValue2;
2432  for( int c = numColsRational() - 1; c >= 0; c-- )
2433  {
2434  _rationalLP->changeMaxObj(c, 0);
2435  _realLP->changeMaxObj(c, 0.0);
2436 
2437  if( lowerRational(c) > 0 )
2438  {
2439  const SVectorRational& colVector = colVectorRational(c);
2440 
2441  for( int i = 0; i < colVector.size(); i++ )
2442  {
2443  shiftValue = colVector.value(i);
2444  shiftValue *= lowerRational(c);
2445  int r = colVector.index(i);
2446 
2447  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2448  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2449 
2450  if( _lowerFinite(_rowTypes[r]) && _upperFinite(_rowTypes[r]) )
2451  {
2452  shiftValue2 = lhsRational(r);
2453  shiftValue2 -= shiftValue;
2454  _rationalLP->changeLhs(r, shiftValue2);
2455  _realLP->changeLhs(r, Real(shiftValue2));
2456 
2457  shiftValue -= rhsRational(r);
2458  shiftValue *= -1;
2459  _rationalLP->changeRhs(r, shiftValue);
2460  _realLP->changeRhs(r, Real(shiftValue));
2461  }
2462  else if( _lowerFinite(_rowTypes[r]) )
2463  {
2464  shiftValue -= lhsRational(r);
2465  shiftValue *= -1;
2466  _rationalLP->changeLhs(r, shiftValue);
2467  _realLP->changeLhs(r, Real(shiftValue));
2468  }
2469  else if( _upperFinite(_rowTypes[r]) )
2470  {
2471  shiftValue -= rhsRational(r);
2472  shiftValue *= -1;
2473  _rationalLP->changeRhs(r, shiftValue);
2474  _realLP->changeRhs(r, Real(shiftValue));
2475  }
2476  }
2477 
2478  assert((upperRational(c) < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2479  if( _upperFinite(_colTypes[c]) )
2480  {
2482  _realLP->changeBounds(c, 0.0, Real(upperRational(c)));
2483  }
2484  else if( _realLP->upper(c) < realParam(SoPlex::INFTY) )
2485  {
2486  _rationalLP->changeLower(c, 0);
2488  }
2489  else
2490  {
2491  _rationalLP->changeLower(c, 0);
2492  _realLP->changeLower(c, 0.0);
2493  }
2494  }
2495  else if( upperRational(c) < 0 )
2496  {
2497  const SVectorRational& colVector = colVectorRational(c);
2498 
2499  for( int i = 0; i < colVector.size(); i++ )
2500  {
2501  shiftValue = colVector.value(i);
2502  shiftValue *= upperRational(c);
2503  int r = colVector.index(i);
2504 
2505  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2506  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2507 
2508  if( _lowerFinite(_rowTypes[r]) && _upperFinite(_rowTypes[r]) )
2509  {
2510  shiftValue2 = lhsRational(r);
2511  shiftValue2 -= shiftValue;
2512  _rationalLP->changeLhs(r, shiftValue2);
2513  _realLP->changeLhs(r, Real(shiftValue2));
2514 
2515  shiftValue -= rhsRational(r);
2516  shiftValue *= -1;
2517  _rationalLP->changeRhs(r, shiftValue);
2518  _realLP->changeRhs(r, Real(shiftValue));
2519  }
2520  else if( _lowerFinite(_rowTypes[r]) )
2521  {
2522  shiftValue -= lhsRational(r);
2523  shiftValue *= -1;
2524  _rationalLP->changeLhs(r, shiftValue);
2525  _realLP->changeLhs(r, Real(shiftValue));
2526  }
2527  else if( _upperFinite(_rowTypes[r]) )
2528  {
2529  shiftValue -= rhsRational(r);
2530  shiftValue *= -1;
2531  _rationalLP->changeRhs(r, shiftValue);
2532  _realLP->changeRhs(r, Real(shiftValue));
2533  }
2534  }
2535 
2536  assert((lowerRational(c) > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2537  if( _lowerFinite(_colTypes[c]) )
2538  {
2540  _realLP->changeBounds(c, Real(lowerRational(c)), 0.0);
2541  }
2542  else if( _realLP->lower(c) > -realParam(SoPlex::INFTY) )
2543  {
2544  _rationalLP->changeUpper(c, 0);
2546  }
2547  else
2548  {
2549  _rationalLP->changeUpper(c, 0);
2550  _realLP->changeUpper(c, 0.0);
2551  }
2552  }
2553  else
2554  {
2555  if( _lowerFinite(_colTypes[c]) )
2557  else if( _realLP->lower(c) > -realParam(SoPlex::INFTY) )
2559  if( _upperFinite(_colTypes[c]) )
2561  else if( _realLP->upper(c) < realParam(SoPlex::INFTY) )
2563  }
2564 
2565  assert(lowerReal(c) <= upperReal(c));
2566  }
2567 
2568  // homogenize sides
2569  _tauColVector.clear();
2570  for( int r = numRowsRational() - 1; r >= 0; r-- )
2571  {
2572  if( lhsRational(r) > 0 )
2573  {
2574  _tauColVector.add(r, lhsRational(r));
2575  assert((rhsRational(r) < _rationalPosInfty) == _upperFinite(_rowTypes[r]));
2576  if( _upperFinite(_rowTypes[r]) )
2577  {
2579  _realLP->changeRange(r, 0.0, Real(rhsRational(r)));
2580  }
2581  else
2582  {
2583  _rationalLP->changeLhs(r, 0);
2584  _realLP->changeLhs(r, 0.0);
2585  if( _realLP->rhs(r) < realParam(SoPlex::INFTY) )
2587  }
2588  }
2589  else if( rhsRational(r) < 0 )
2590  {
2591  _tauColVector.add(r, rhsRational(r));
2592  assert((lhsRational(r) > _rationalNegInfty) == _lowerFinite(_rowTypes[r]));
2593  if( _lowerFinite(_rowTypes[r]) )
2594  {
2596  _realLP->changeRange(r, Real(lhsRational(r)), 0.0);
2597  }
2598  else
2599  {
2600  _rationalLP->changeRhs(r, 0);
2601  _realLP->changeRhs(r, 0.0);
2602  if( _realLP->lhs(r) > -realParam(SoPlex::INFTY) )
2604  }
2605  }
2606  else
2607  {
2608  if( _lowerFinite(_rowTypes[r]) )
2609  _realLP->changeLhs(r, Real(lhsRational(r)));
2610  else if( _realLP->lhs(r) > -realParam(SoPlex::INFTY) )
2612  if( _upperFinite(_rowTypes[r]) )
2613  _realLP->changeRhs(r, Real(rhsRational(r)));
2614  else if( _realLP->rhs(r) < realParam(SoPlex::INFTY) )
2616  }
2617 
2618  assert(rhsReal(r) <= rhsReal(r));
2619  }
2620 
2621  ///@todo exploit this case by returning without LP solving
2622  if( _tauColVector.size() == 0 )
2623  {
2624  MSG_INFO3( spxout, spxout << "LP is trivially feasible.\n" );
2625  }
2626 
2627  // add artificial column
2628  SPxColId id;
2629  _tauColVector *= -1;
2630  _rationalLP->addCol(id,
2632  _tauColVector, 1, 0));
2633  _realLP->addCol(id,
2635  DSVectorReal(_tauColVector), 1.0, 0.0));
2637 
2638  // adjust basis
2639  if( _hasBasis )
2640  {
2642  }
2643 
2644  // invalidate rational basis factorization
2646 
2647  // print LP if in debug mode
2648  MSG_DEBUG( _realLP->writeFile("afterTransFeas.lp", 0, 0, 0) );
2649 
2650  // stop timing
2652  }
2653 
2654 
2655 
2656  /// undoes transformation to feasibility problem
2657  void SoPlex::_untransformFeasibility(SolRational& sol, bool infeasible)
2658  {
2659  // start timing
2661 
2662  // print LP if in debug mode
2663  MSG_DEBUG( _realLP->writeFile("beforeUntransFeas.lp", 0, 0, 0) );
2664 
2665  int numOrigCols = numColsRational() - 1;
2666 
2667  // adjust solution and basis
2668  if( infeasible )
2669  {
2670  assert(sol._isDualFeasible);
2671  assert(sol._primal[numOrigCols] < 1);
2672 
2673  sol._isPrimalFeasible= false;
2674  sol._hasPrimalRay = false;
2675  sol._isDualFeasible = false;
2676  sol._hasDualFarkas = true;
2677 
2678  sol._dualFarkas = sol._dual;
2679 
2680  _hasBasis = false;
2681  _basisStatusCols.reSize(numOrigCols);
2682  }
2683  else if( sol._isPrimalFeasible)
2684  {
2685  assert(sol._primal[numOrigCols] >= 1);
2686 
2687  sol._hasPrimalRay = false;
2688  sol._isDualFeasible = false;
2689  sol._hasDualFarkas = false;
2690 
2691  if( sol._primal[numOrigCols] != 1 )
2692  {
2693  sol._slacks /= sol._primal[numOrigCols];
2694  for( int i = 0; i < numOrigCols; i++ )
2695  sol._primal[i] /= sol._primal[numOrigCols];
2696  sol._primal[numOrigCols] = 1;
2697  }
2698 
2699  sol._primal.reDim(numOrigCols);
2700  sol._slacks -= _rationalLP->colVector(numOrigCols);
2701 
2702  _hasBasis = (_basisStatusCols[numOrigCols] != SPxSolver::BASIC);
2703  _basisStatusCols.reSize(numOrigCols);
2704  }
2705  else
2706  {
2707  _hasBasis = false;
2708  _basisStatusCols.reSize(numOrigCols);
2709  }
2710 
2711  // restore right-hand side
2712  for( int r = numRowsRational() - 1; r >= 0; r-- )
2713  {
2715  || _feasLhs[r] - lhsRational(r) == _feasRhs[r] - rhsRational(r));
2716 
2717  if( _lowerFinite(_rowTypes[r]) )
2718  {
2719  _rationalLP->changeLhs(r, _feasLhs[r]);
2720  _realLP->changeLhs(r, Real(_feasLhs[r]));
2721  }
2722  else if( _realLP->lhs(r) > -realParam(SoPlex::INFTY) )
2724  assert(_lowerFinite(_rowTypes[r]) == (lhsRational(r) > _rationalNegInfty));
2725  assert(_lowerFinite(_rowTypes[r]) == (lhsReal(r) > -realParam(SoPlex::INFTY)));
2726 
2727  if( _upperFinite(_rowTypes[r]) )
2728  {
2729  _rationalLP->changeRhs(r, _feasRhs[r]);
2730  _realLP->changeRhs(r, Real(_feasRhs[r]));
2731  }
2732  else if( _realLP->rhs(r) < realParam(SoPlex::INFTY) )
2734  assert(_upperFinite(_rowTypes[r]) == (rhsRational(r) < _rationalPosInfty));
2735  assert(_upperFinite(_rowTypes[r]) == (rhsReal(r) < realParam(SoPlex::INFTY)));
2736 
2737  assert(lhsReal(r) <= rhsReal(r));
2738  }
2739 
2740  // unshift primal space and restore objective coefficients
2741  Rational shiftValue;
2742  for( int c = numOrigCols - 1; c >= 0; c-- )
2743  {
2744  bool shifted = (_lowerFinite(_colTypes[c]) && _feasLower[c] > 0) || (_upperFinite(_colTypes[c]) && _feasUpper[c] < 0);
2745  assert(shifted || !_lowerFinite(_colTypes[c]) || _feasLower[c] == lowerRational(c));
2746  assert(shifted || !_upperFinite(_colTypes[c]) || _feasUpper[c] == upperRational(c));
2747 #ifdef SOPLEX_WITH_GMP
2749  || _feasLower[c] - lowerRational(c) == _feasUpper[c] - upperRational(c));
2750 #endif
2751 
2752  if( shifted )
2753  {
2754  if( _lowerFinite(_colTypes[c]) )
2755  {
2756  shiftValue = _feasLower[c];
2757  shiftValue -= lowerRational(c);
2758  }
2759  else if( _upperFinite(_colTypes[c]) )
2760  {
2761  shiftValue = _feasUpper[c];
2762  shiftValue -= upperRational(c);
2763  }
2764  if( sol._isPrimalFeasible)
2765  {
2766  sol._primal[c] += shiftValue;
2767  sol._slacks.multAdd(shiftValue, _rationalLP->colVector(c));
2768  }
2769  }
2770 
2771  if( _lowerFinite(_colTypes[c]) )
2772  {
2773  if( shifted )
2776  }
2777  else if( _realLP->lower(c) > -realParam(SoPlex::INFTY) )
2779  assert(_lowerFinite(_colTypes[c]) == (lowerRational(c) > -_rationalPosInfty));
2780  assert(_lowerFinite(_colTypes[c]) == (lowerReal(c) > -realParam(SoPlex::INFTY)));
2781 
2782  if( _upperFinite(_colTypes[c]) )
2783  {
2784  if( shifted )
2787  }
2788  else if( _realLP->upper(c) < realParam(SoPlex::INFTY) )
2790  assert(_upperFinite(_colTypes[c]) == (upperRational(c) < _rationalPosInfty));
2791  assert(_upperFinite(_colTypes[c]) == (upperReal(c) < realParam(SoPlex::INFTY)));
2792 
2794  _realLP->changeMaxObj(c, Real(_feasObj[c]));
2795 
2796  assert(lowerReal(c) <= upperReal(c));
2797  }
2798 
2799  // remove last column
2800  _rationalLP->removeCol(numOrigCols);
2801  _realLP->removeCol(numOrigCols);
2802  _colTypes.reSize(numOrigCols);
2803 
2804  // invalidate rational basis factorization
2806 
2807  // print LP if in debug mode
2808  MSG_DEBUG( _realLP->writeFile("afterUntransFeas.lp", 0, 0, 0) );
2809 
2810  // stop timing
2812 
2813 #ifndef NDEBUG
2814 #ifdef SOPLEX_WITH_GMP
2815  if( sol._isPrimalFeasible)
2816  {
2817  DVectorRational activity(numRowsRational());
2818  _rationalLP->computePrimalActivity(sol._primal, activity);
2819  assert(sol._slacks == activity);
2820  }
2821 #endif
2822 #endif
2823  }
2824 
2825  /** computes radius of infeasibility box implied by an approximate Farkas' proof
2826 
2827  Given constraints of the form \f$ lhs <= Ax <= rhs \f$, a farkas proof y should satisfy \f$ y^T A = 0 \f$ and
2828  \f$ y_+^T lhs - y_-^T rhs > 0 \f$, where \f$ y_+, y_- \f$ denote the positive and negative parts of \f$ y \f$.
2829  If \f$ y \f$ is approximate, it may not satisfy \f$ y^T A = 0 \f$ exactly, but the proof is still valid as long
2830  as the following holds for all potentially feasible \f$ x \f$:
2831 
2832  \f[
2833  y^T Ax < (y_+^T lhs - y_-^T rhs) (*)
2834  \f]
2835 
2836  we may therefore calculate \f$ y^T A \f$ and \f$ y_+^T lhs - y_-^T rhs \f$ exactly and check if the upper and lower
2837  bounds on \f$ x \f$ imply that all feasible \f$ x \f$ satisfy (*), and if not then compute bounds on \f$ x \f$ to
2838  guarantee (*). The simplest way to do this is to compute
2839 
2840  \f[
2841  B = (y_+^T lhs - y_-^T rhs) / \sum_i(|(y^T A)_i|)
2842  \f]
2843 
2844  noting that if every component of \f$ x \f$ has \f$ |x_i| < B \f$, then (*) holds.
2845 
2846  \f$ B \f$ can be increased by iteratively including variable bounds smaller than \f$ B \f$. The speed of this
2847  method can be further improved by using interval arithmetic for all computations. For related information see
2848  Sec. 4 of Neumaier and Shcherbina, Mathematical Programming A, 2004.
2849 
2850  Set transformed to true if this method is called after _transformFeasibility().
2851  */
2852  void SoPlex::_computeInfeasBox(SolRational& sol, bool transformed)
2853  {
2854  assert(sol.hasDualFarkas());
2855 
2856  const VectorRational& lower = transformed ? _feasLower : lowerRational();
2857  const VectorRational& upper = transformed ? _feasUpper : upperRational();
2858  const VectorRational& lhs = transformed ? _feasLhs : lhsRational();
2859  const VectorRational& rhs = transformed ? _feasRhs : rhsRational();
2860  const VectorRational& y = sol._dualFarkas;
2861 
2862  const int numRows = numRowsRational();
2863  const int numCols = transformed ? numColsRational() - 1 : numColsRational();
2864 
2865  SSVectorRational ytransA(numColsRational());
2866  Rational ytransb;
2867  Rational temp;
2868 
2869  // prepare ytransA and ytransb; since we want exact arithmetic, we set the zero threshold of the semi-sparse
2870  // vector to zero
2871  ytransA.setEpsilon(0);
2872  ytransA.clear();
2873  ytransb = 0;
2874 
2875  ///@todo this currently works only if all constraints are equations aggregate rows and sides using the multipliers of the Farkas ray
2876  for( int r = 0; r < numRows; r++ )
2877  {
2878  ytransA += y[r] * _rationalLP->rowVector(r);
2879  ytransb += y[r] * (y[r] > 0 ? lhs[r] : rhs[r]);
2880  }
2881 
2882  // if we work on the feasibility problem, we ignore the last column
2883  if( transformed )
2884  ytransA.reDim(numCols);
2885 
2886  MSG_DEBUG( std::cout << "ytransb = " << rationalToString(ytransb) << "\n" );
2887 
2888  // if we choose minus ytransb as vector of multipliers for the bound constraints on the variables, we obtain an
2889  // exactly feasible dual solution for the LP with zero objective function; we aggregate the bounds of the
2890  // variables accordingly and store its negation in temp
2891  temp = 0;
2892  bool isTempFinite = true;
2893  for( int c = 0; c < numCols && isTempFinite; c++ )
2894  {
2895  const Rational& minusRedCost = ytransA[c];
2896 
2897  if( minusRedCost > 0 )
2898  {
2899  assert((upper[c] < _rationalPosInfty) == _upperFinite(_colTypes[c]));
2900  if( _upperFinite(_colTypes[c]) )
2901  temp.addProduct(minusRedCost, upper[c]);
2902  else
2903  isTempFinite = false;
2904  }
2905  else if( minusRedCost < 0 )
2906  {
2907  assert((lower[c] > _rationalNegInfty) == _lowerFinite(_colTypes[c]));
2908  if( _lowerFinite(_colTypes[c]) )
2909  temp.addProduct(minusRedCost, lower[c]);
2910  else
2911  isTempFinite = false;
2912  }
2913  }
2914 
2915  MSG_DEBUG( std::cout << "max ytransA*[x_l,x_u] = " << (isTempFinite ? rationalToString(temp) : "infinite") << "\n" );
2916 
2917  // ytransb - temp is the increase in the dual objective along the Farkas ray; if this is positive, the dual is
2918  // unbounded and certifies primal infeasibility
2919  if( isTempFinite && temp < ytransb )
2920  {
2921  MSG_INFO1( spxout, spxout << "Farkas infeasibility proof verified exactly. (1)\n" );
2922  return;
2923  }
2924 
2925  // ensure that array of nonzero elements in ytransA is available
2926  assert(ytransA.isSetup());
2927  ytransA.setup();
2928 
2929  // if ytransb is negative, try to make it zero by including a positive lower bound or a negative upper bound
2930  if( ytransb < 0 )
2931  {
2932  for( int c = 0; c < numCols; c++ )
2933  {
2934  if( lower[c] > 0 )
2935  {
2936  ytransA.setValue(c, ytransA[c] - ytransb / lower[c]);
2937  ytransb = 0;
2938  break;
2939  }
2940  else if( upper[c] < 0 )
2941  {
2942  ytransA.setValue(c, ytransA[c] - ytransb / upper[c]);
2943  ytransb = 0;
2944  break;
2945  }
2946  }
2947  }
2948 
2949  // if ytransb is still zero then the zero solution is inside the bounds and cannot be cut off by the Farkas
2950  // constraint; in this case, we cannot compute a Farkas box
2951  if( ytransb < 0 )
2952  {
2953  MSG_INFO1( spxout, spxout << "Approximate Farkas proof to weak. Could not compute Farkas box. (1)\n" );
2954  return;
2955  }
2956 
2957  // compute the one norm of ytransA
2958  temp = 0;
2959  const int size = ytransA.size();
2960  for( int n = 0; n < size; n++ )
2961  temp += spxAbs(ytransA.value(n));
2962 
2963  // if the one norm is zero then ytransA is zero the Farkas proof should have been verified above
2964  assert(temp != 0);
2965 
2966  // initialize variables in loop: size of Farkas box B, flag whether B has been increased, and number of current
2967  // nonzero in ytransA
2968  Rational B = ytransb / temp;
2969  bool success = false;
2970  int n = 0;
2971 
2972  // loop through nonzeros of ytransA
2973  MSG_DEBUG( std::cout << "B = " << rationalToString(B) << "\n" );
2974  assert(ytransb >= 0);
2975 
2976  while( true )
2977  {
2978  // if all nonzeros have been inspected once without increasing B, we abort; otherwise, we start another round
2979  if( n >= ytransA.size() )
2980  {
2981  if( !success )
2982  break;
2983 
2984  success = false;
2985  n = 0;
2986  }
2987 
2988  // get Farkas multiplier of the bound constraint as minus the value in ytransA
2989  const Rational& minusRedCost = ytransA.value(n);
2990  int colIdx = ytransA.index(n);
2991 
2992  // if the multiplier is positive we inspect the lower bound: if it is finite and within the Farkas box, we can
2993  // increase B by including it in the Farkas proof
2994  assert((upper[colIdx] < _rationalPosInfty) == _upperFinite(_colTypes[colIdx]));
2995  assert((lower[colIdx] > _rationalNegInfty) == _lowerFinite(_colTypes[colIdx]));
2996  if( minusRedCost < 0 && lower[colIdx] > -B && _lowerFinite(_colTypes[colIdx]) )
2997  {
2998  ytransA.clearNum(n);
2999  ytransb.subProduct(minusRedCost, lower[colIdx]);
3000  temp += minusRedCost;
3001 
3002  assert(ytransb >= 0);
3003  assert(temp >= 0);
3004  assert(temp == 0 || ytransb / temp > B);
3005 
3006  // if ytransA and ytransb are zero, we have 0^T x >= 0 and cannot compute a Farkas box
3007  if( temp == 0 && ytransb == 0 )
3008  {
3009  MSG_INFO1( spxout, spxout << "Approximate Farkas proof to weak. Could not compute Farkas box. (2)\n" );
3010  return;
3011  }
3012  // if ytransb is positive and ytransA is zero, we have 0^T x > 0, proving infeasibility
3013  else if( temp == 0 )
3014  {
3015  assert(ytransb > 0);
3016  MSG_INFO1( spxout, spxout << "Farkas infeasibility proof verified exactly. (2)\n" );
3017  return;
3018  }
3019  else
3020  {
3021  B = ytransb / temp;
3022  MSG_DEBUG( std::cout << "B = " << rationalToString(B) << "\n" );
3023  }
3024 
3025  success = true;
3026  }
3027  // if the multiplier is negative we inspect the upper bound: if it is finite and within the Farkas box, we can
3028  // increase B by including it in the Farkas proof
3029  else if( minusRedCost > 0 && upper[colIdx] < B && _upperFinite(_colTypes[colIdx]) )
3030  {
3031  ytransA.clearNum(n);
3032  ytransb.subProduct(minusRedCost, upper[colIdx]);
3033  temp -= minusRedCost;
3034 
3035  assert(ytransb >= 0);
3036  assert(temp >= 0);
3037  assert(temp == 0 || ytransb / temp > B);
3038 
3039  // if ytransA and ytransb are zero, we have 0^T x >= 0 and cannot compute a Farkas box
3040  if( temp == 0 && ytransb == 0 )
3041  {
3042  MSG_INFO1( spxout, spxout << "Approximate Farkas proof to weak. Could not compute Farkas box. (2)\n" );
3043  return;
3044  }
3045  // if ytransb is positive and ytransA is zero, we have 0^T x > 0, proving infeasibility
3046  else if( temp == 0 )
3047  {
3048  assert(ytransb > 0);
3049  MSG_INFO1( spxout, spxout << "Farkas infeasibility proof verified exactly. (2)\n" );
3050  return;
3051  }
3052  else
3053  {
3054  B = ytransb / temp;
3055  MSG_DEBUG( std::cout << "B = " << rationalToString(B) << "\n" );
3056  }
3057 
3058  success = true;
3059  }
3060  // the multiplier is zero, we can ignore the bound constraints on this variable
3061  else if( minusRedCost == 0 )
3062  ytransA.clearNum(n);
3063  // currently this bound cannot be used to increase B; we will check it again in the next round, because B might
3064  // have increased by then
3065  else
3066  n++;
3067  }
3068 
3069  if( B > 0 )
3070  {
3071  MSG_INFO1( spxout, spxout << "Computed Farkas box: provably no feasible solutions with components less than "
3072  << rationalToString(B) << " in absolute value.\n" );
3073  }
3074  }
3075 
3076 
3077 
3078  /// solves real LP during iterative refinement
3079  SPxSolver::Status SoPlex::_solveRealForRational(bool fromscratch, VectorReal& primal, VectorReal& dual, DataArray< SPxSolver::VarStatus >& basisStatusRows, DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& returnedBasis)
3080  {
3081  assert(_isConsistent());
3082 
3083  assert(_solver.nRows() == numRowsRational());
3084  assert(_solver.nCols() == numColsRational());
3085  assert(primal.dim() == numColsRational());
3086  assert(dual.dim() == numRowsRational());
3087 
3089 
3090 #ifndef SOPLEX_MANUAL_ALT
3091  if( fromscratch || !_hasBasis )
3093  else
3095 #else
3097 #endif
3098 
3099  // start timing
3101 
3102  // if preprocessing is applied, we need to restore the original LP at the end
3103  SPxLPRational* rationalLP = 0;
3104  if( _simplifier != 0 || _scaler != 0 )
3105  {
3106  spx_alloc(rationalLP);
3107  rationalLP = new (rationalLP) SPxLPRational(_solver);
3108  }
3109 
3110  // if preprocessing is applied, the basis may change, hence invalidate the rational basis factorization; if no
3111  if( _simplifier != 0 || _scaler != 0 )
3113 
3114  // stop timing
3116 
3117  returnedBasis = false;
3118  try
3119  {
3120  // apply problem simplification
3121  SPxSimplifier::Result simplificationStatus = SPxSimplifier::OKAY;
3122  if( _simplifier != 0 )
3123  {
3124  // do not remove bounds of boxed variables or sides of ranged rows if bound flipping is used
3127  }
3128 
3129  // apply scaling after the simplification
3130  if( _scaler != 0 && simplificationStatus == SPxSimplifier::OKAY )
3131  _scaler->scale(_solver, false);
3132 
3133  // run the simplex method if problem has not been solved by the simplifier
3134  if( simplificationStatus == SPxSimplifier::OKAY )
3135  {
3136  MSG_INFO1( spxout, spxout << std::endl );
3137 
3139 
3140  MSG_INFO1( spxout, spxout << std::endl );
3141  }
3142 
3143  ///@todo move to private helper methods
3144  // evaluate status flag
3145  if( simplificationStatus == SPxSimplifier::INFEASIBLE )
3146  result = SPxSolver::INFEASIBLE;
3147  else if( simplificationStatus == SPxSimplifier::DUAL_INFEASIBLE )
3148  result = SPxSolver::INForUNBD;
3149  else if( simplificationStatus == SPxSimplifier::UNBOUNDED )
3150  result = SPxSolver::UNBOUNDED;
3151  else if( simplificationStatus == SPxSimplifier::VANISHED || simplificationStatus == SPxSimplifier::OKAY )
3152  {
3153  result = simplificationStatus == SPxSimplifier::VANISHED ? SPxSolver::OPTIMAL : _solver.status();
3154 
3155  ///@todo move to private helper methods
3156  // process result
3157  switch( result )
3158  {
3159  case SPxSolver::OPTIMAL:
3160  // unsimplify if simplifier is active and LP is solved to optimality; this must be done here and not at solution
3161  // query, because we want to have the basis for the original problem
3162  if( _simplifier != 0 )
3163  {
3164  assert(!_simplifier->isUnsimplified());
3165  assert(simplificationStatus == SPxSimplifier::VANISHED || simplificationStatus == SPxSimplifier::OKAY);
3166 
3167  bool vanished = simplificationStatus == SPxSimplifier::VANISHED;
3168 
3169  // get solution vectors for transformed problem
3170  DVectorReal tmpPrimal(vanished ? 0 : _solver.nCols());
3171  DVectorReal tmpSlacks(vanished ? 0 : _solver.nRows());
3172  DVectorReal tmpDual(vanished ? 0 : _solver.nRows());
3173  DVectorReal tmpRedCost(vanished ? 0 : _solver.nCols());
3174 
3175  if( !vanished )
3176  {
3177  assert(_solver.status() == SPxSolver::OPTIMAL);
3178 
3179  _solver.getPrimal(tmpPrimal);
3180  _solver.getSlacks(tmpSlacks);
3181  _solver.getDual(tmpDual);
3182  _solver.getRedCost(tmpRedCost);
3183 
3184  // unscale vectors
3185  if( _scaler != 0 )
3186  {
3187  _scaler->unscalePrimal(_solver, tmpPrimal);
3188  _scaler->unscaleSlacks(_solver, tmpSlacks);
3189  _scaler->unscaleDual(_solver, tmpDual);
3190  _scaler->unscaleRedCost(_solver, tmpRedCost);
3191  }
3192 
3193  // get basis of transformed problem
3194  basisStatusRows.reSize(_solver.nRows());
3195  basisStatusCols.reSize(_solver.nCols());
3196  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(), basisStatusCols.size());
3197  }
3198 
3199  ///@todo catch exception
3200  _simplifier->unsimplify(tmpPrimal, tmpDual, tmpSlacks, tmpRedCost, basisStatusRows.get_ptr(), basisStatusCols.get_ptr());
3201 
3202  // store basis for original problem
3203  basisStatusRows.reSize(numRowsRational());
3204  basisStatusCols.reSize(numColsRational());
3205  _simplifier->getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(), basisStatusCols.size());
3206  returnedBasis = true;
3207 
3208  primal = _simplifier->unsimplifiedPrimal();
3209  dual = _simplifier->unsimplifiedDual();
3210  }
3211  // if the original problem is not in the solver because of scaling, we also need to store the basis
3212  else
3213  {
3214  _solver.getPrimal(primal);
3215  _solver.getDual(dual);
3216 
3217  // unscale vectors
3218  if( _scaler != 0 )
3219  {
3220  _scaler->unscalePrimal(_solver, primal);
3221  _scaler->unscaleDual(_solver, dual);
3222  }
3223 
3224  // get basis of transformed problem
3225  basisStatusRows.reSize(_solver.nRows());
3226  basisStatusCols.reSize(_solver.nCols());
3227  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(), basisStatusCols.size());
3228  returnedBasis = true;
3229  }
3230  break;
3231 
3234  {
3235  _solver.getPrimal(primal);
3236  _solver.getDual(dual);
3237 
3238  // unscale vectors
3239  if( _scaler != 0 )
3240  {
3241  _scaler->unscalePrimal(_solver, primal);
3242  _scaler->unscaleDual(_solver, dual);
3243  }
3244 
3245  // get basis of transformed problem
3246  basisStatusRows.reSize(_solver.nRows());
3247  basisStatusCols.reSize(_solver.nCols());
3248  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(), basisStatusCols.size());
3249  returnedBasis = true;
3250  result = SPxSolver::OPTIMAL;
3251  }
3252  break;
3253  case SPxSolver::ABORT_TIME:
3254  case SPxSolver::ABORT_ITER:
3256  case SPxSolver::REGULAR:
3257  case SPxSolver::RUNNING:
3258  case SPxSolver::UNBOUNDED:
3259  break;
3260  case SPxSolver::INFEASIBLE:
3261  // if simplifier is active we cannot return a Farkas ray currently
3262  if( _simplifier != 0 )
3263  break;
3264 
3265  // return Farkas ray as dual solution
3266  _solver.getDualfarkas(dual);
3267 
3268  // unscale vectors
3269  if( _scaler != 0 )
3270  _scaler->unscaleDual(_solver, dual);
3271 
3272  // if the original problem is not in the solver because of scaling, we also need to store the basis
3273  basisStatusRows.reSize(_solver.nRows());
3274  basisStatusCols.reSize(_solver.nCols());
3275  _solver.getBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr(), basisStatusRows.size(), basisStatusCols.size());
3276  returnedBasis = true;
3277  break;
3278 
3279  case SPxSolver::INForUNBD:
3280  case SPxSolver::SINGULAR:
3281  default:
3282  break;
3283  }
3284  }
3285  }
3286  catch( ... )
3287  {
3288  MSG_INFO1( spxout, spxout << "Exception thrown during floating-point solve.\n" );
3289  result = SPxSolver::ERROR;
3290  }
3291 
3292  // restore original LP if necessary
3293  if( _simplifier != 0 || _scaler != 0 )
3294  {
3295  assert(rationalLP != 0);
3296  _solver.loadLP((SPxLPReal)(*rationalLP));
3297  rationalLP->~SPxLPRational();
3298  spx_free(rationalLP);
3299  if( _hasBasis )
3300  _solver.setBasis(basisStatusRows.get_ptr(), basisStatusCols.get_ptr());
3301  }
3302 
3303  return result;
3304  }
3305 
3306 
3307 
3308  /// solves real LP with recovery mechanism
3309  SPxSolver::Status SoPlex::_solveRealStable(bool acceptUnbounded, bool acceptInfeasible, VectorReal& primal, VectorReal& dual, DataArray< SPxSolver::VarStatus >& basisStatusRows, DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& returnedBasis, const bool forceNoSimplifier)
3310  {
3312 
3313  bool fromScratch = false;
3314  bool solved = false;
3315  bool solvedFromScratch = false;
3316  bool initialSolve = true;
3317  bool increasedMarkowitz = false;
3318  bool relaxedTolerances = false;
3319  bool tightenedTolerances = false;
3320  bool switchedScaler = false;
3321  bool switchedSimplifier = false;
3322  bool switchedRatiotester = false;
3323  bool switchedPricer = false;
3324  bool turnedoffPre = false;
3325 
3326  Real markowitz = _slufactor.markowitz();
3327  int ratiotester = intParam(SoPlex::RATIOTESTER);
3328  int pricer = intParam(SoPlex::PRICER);
3329  int simplifier = intParam(SoPlex::SIMPLIFIER);
3330  int scaler = intParam(SoPlex::SCALER);
3331  int type = intParam(SoPlex::ALGORITHM);
3332 
3333  if( forceNoSimplifier )
3335 
3336  while( true )
3337  {
3338  assert(!increasedMarkowitz || GE(_slufactor.markowitz(), 0.9));
3339 
3340  result = _solveRealForRational(fromScratch, primal, dual, basisStatusRows, basisStatusCols, returnedBasis);
3341 
3342  solved = (result == SPxSolver::OPTIMAL)
3343  || (result == SPxSolver::INFEASIBLE && acceptInfeasible)
3344  || (result == SPxSolver::UNBOUNDED && acceptUnbounded);
3345 
3346  if( solved )
3347  break;
3348 
3349 // if( _isSolveStopped() )
3350 // break;
3351 
3352  if( initialSolve )
3353  {
3354  MSG_INFO1( spxout, spxout << "Numerical troubles during floating-point solve." << std::endl );
3355  initialSolve = false;
3356  }
3357 
3358  if( !turnedoffPre
3360  {
3361  MSG_INFO1( spxout, spxout << "Turning off preprocessing." << std::endl );
3362 
3363  turnedoffPre = true;
3364 
3367 
3368  fromScratch = true;
3369  _solver.reLoad();
3370  solvedFromScratch = true;
3371  continue;
3372  }
3373 
3374  setIntParam(SoPlex::SCALER, scaler);
3375  setIntParam(SoPlex::SIMPLIFIER, simplifier);
3376 
3377  if( !increasedMarkowitz )
3378  {
3379  MSG_INFO1( spxout, spxout << "Increasing Markowitz threshold." << std::endl );
3380 
3381  _slufactor.setMarkowitz(0.9);
3382  increasedMarkowitz = true;
3383  try
3384  {
3385  _solver.factorize();
3386  continue;
3387  }
3388  catch( ... )
3389  {
3390  MSG_DEBUG( std::cout << std::endl << "Factorization failed." << std::endl );
3391  }
3392  }
3393 
3394  if( !solvedFromScratch )
3395  {
3396  MSG_INFO1( spxout, spxout << "Solving from scratch." << std::endl );
3397 
3398  fromScratch = true;
3399  _solver.reLoad();
3400 
3401  solvedFromScratch = true;
3402  continue;
3403  }
3404 
3405  setIntParam(SoPlex::RATIOTESTER, ratiotester);
3406  setIntParam(SoPlex::PRICER, pricer);
3407 
3408  if( !switchedScaler )
3409  {
3410  MSG_INFO1( spxout, spxout << "Switching scaling." << std::endl );
3411 
3412  if( scaler == int(SoPlex::SCALER_OFF) )
3414  else
3416 
3417  fromScratch = true;
3418  _solver.reLoad();
3419 
3420  solvedFromScratch = true;
3421  switchedScaler = true;
3422  continue;
3423  }
3424 
3425  if( !switchedSimplifier && !forceNoSimplifier )
3426  {
3427  MSG_INFO1( spxout, spxout << "Switching simplification." << std::endl );
3428 
3429  if( simplifier == int(SoPlex::SIMPLIFIER_OFF) )
3431  else
3433 
3434  fromScratch = true;
3435  _solver.reLoad();
3436 
3437  solvedFromScratch = true;
3438  switchedSimplifier = true;
3439  continue;
3440  }
3441 
3443 
3444  if( !relaxedTolerances )
3445  {
3446  MSG_INFO1( spxout, spxout << "Relaxing tolerances." << std::endl );
3447 
3449  _solver.setDelta((_solver.feastol() * 1e3 > 1e-3) ? 1e-3 : (_solver.feastol() * 1e3));
3450  relaxedTolerances = _solver.feastol() >= 1e-3;
3451  solvedFromScratch = false;
3452  continue;
3453  }
3454 
3455  if( !tightenedTolerances && result != SPxSolver::INFEASIBLE )
3456  {
3457  MSG_INFO1( spxout, spxout << "Tightening tolerances." << std::endl );
3458 
3460  _solver.setDelta(_solver.feastol() * 1e-3 < 1e-9 ? 1e-9 : _solver.feastol() * 1e-3);
3461  tightenedTolerances = _solver.feastol() <= 1e-9;
3462  solvedFromScratch = false;
3463  continue;
3464  }
3465 
3467 
3468  if( !switchedRatiotester )
3469  {
3470  MSG_INFO1( spxout, spxout << "Switching ratio test." << std::endl );
3471 
3475  else
3477  switchedRatiotester = true;
3478  solvedFromScratch = false;
3479  continue;
3480  }
3481 
3482  if( !switchedPricer )
3483  {
3484  MSG_INFO1( spxout, spxout << "Switching pricer." << std::endl );
3485 
3487  if( _solver.pricer() != (SPxPricer*)&_pricerDevex )
3489  else
3491  switchedPricer = true;
3492  solvedFromScratch = false;
3493  continue;
3494  }
3495 
3496  MSG_INFO1( spxout, spxout << "Giving up." << std::endl );
3497 
3498  break;
3499  }
3500 
3503  _slufactor.setMarkowitz(markowitz);
3504 
3505  setIntParam(SoPlex::RATIOTESTER, ratiotester);
3506  setIntParam(SoPlex::PRICER, pricer);
3507  setIntParam(SoPlex::SIMPLIFIER, simplifier);
3508  setIntParam(SoPlex::SCALER, scaler);
3510 
3511  return result;
3512  }
3513 
3514 
3515 
3516  /// computes rational inverse of basis matrix as defined by _rationalLUSolverBind
3518  {
3521 
3522  const int matrixdim = numRowsRational();
3523  assert(_rationalLUSolverBind.size() == matrixdim);
3524 
3525  DataArray< const SVectorRational* > matrix(matrixdim);
3526  _rationalLUSolverBind.reSize(matrixdim);
3527 
3528  for( int i = 0; i < matrixdim; i++ )
3529  {
3530  if( _rationalLUSolverBind[i] >= 0 )
3531  {
3532  assert(_rationalLUSolverBind[i] < numColsRational());
3533  matrix[i] = &colVectorRational(_rationalLUSolverBind[i]);
3534  }
3535  else
3536  {
3537  assert(-1 - _rationalLUSolverBind[i] >= 0);
3538  assert(-1 - _rationalLUSolverBind[i] < numRowsRational());
3539  matrix[i] = _unitVectorRational(-1 - _rationalLUSolverBind[i]);
3540  }
3541  }
3542 
3543  // load and factorize rational basis matrix
3546  else
3548  _rationalLUSolver.load(matrix.get_ptr(), matrixdim);
3549 
3550  // record statistics
3554 
3556  {
3557  MSG_INFO2( spxout, spxout << "Rational factorization hit time limit.\n" );
3558  }
3560  {
3561  MSG_INFO1( spxout, spxout << "Error performing rational LU factorization.\n" );
3562  }
3563 
3564  return;
3565  }
3566 
3567 
3568 
3569  /// factorizes rational basis matrix in column representation
3570  void SoPlex::_factorizeColumnRational(SolRational& sol, DataArray< SPxSolver::VarStatus >& basisStatusRows, DataArray< SPxSolver::VarStatus >& basisStatusCols, bool& stoppedTime, bool& stoppedIter, bool& error, bool& optimal)
3571  {
3572  // start rational solving time
3574 
3575  stoppedTime = false;
3576  stoppedIter = false;
3577  error = false;
3578  optimal = false;
3579 
3580  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
3581  const int matrixdim = numRowsRational();
3582  bool loadMatrix = (_rationalLUSolver.status() == SLinSolverRational::UNLOADED
3584  int numBasicRows;
3585 
3586  assert(loadMatrix || matrixdim == _rationalLUSolver.dim());
3587  assert(loadMatrix || matrixdim == _rationalLUSolverBind.size());
3588  if( !loadMatrix && (matrixdim != _rationalLUSolver.dim() || matrixdim != _rationalLUSolverBind.size()) )
3589  {
3590  MSG_WARNING( spxout, spxout << "Warning: dimensioning error in rational matrix factorization (recovered).\n" );
3591  loadMatrix = true;
3592  }
3593 
3594  _workSol._primal.reDim(matrixdim);
3595  _workSol._slacks.reDim(matrixdim);
3596  _workSol._dual.reDim(matrixdim);
3597  _workSol._redCost.reDim(numColsRational() > matrixdim ? numColsRational() : matrixdim);
3598  if( loadMatrix )
3599  _rationalLUSolverBind.reSize(matrixdim);
3600 
3601  DVectorRational& basicPrimalRhs = _workSol._slacks;
3602  DVectorRational& basicDualRhs = _workSol._redCost;
3603  DVectorRational& basicPrimal = _workSol._primal;
3604  DVectorRational& basicDual = _workSol._dual;
3605 
3606  Rational violation;
3607  Rational primalViolation;
3608  Rational dualViolation;
3609  bool primalFeasible = false;
3610  bool dualFeasible = false;
3611 
3612  assert(basisStatusCols.size() == numColsRational());
3613  assert(basisStatusRows.size() == numRowsRational());
3614 
3615  int j = 0;
3616  for( int i = 0; i < basisStatusRows.size(); i++ )
3617  {
3618  if( basisStatusRows[i] == SPxSolver::BASIC && j < matrixdim )
3619  {
3620  basicPrimalRhs[i] = 0;
3621  basicDualRhs[j] = 0;
3622  if( loadMatrix )
3623  _rationalLUSolverBind[j] = -1 - i;
3624  j++;
3625  }
3626  else if( basisStatusRows[i] == SPxSolver::ON_LOWER )
3627  basicPrimalRhs[i] = lhsRational(i);
3628  else if( basisStatusRows[i] == SPxSolver::ON_UPPER )
3629  basicPrimalRhs[i] = rhsRational(i);
3630  else if( basisStatusRows[i] == SPxSolver::ZERO )
3631  basicPrimalRhs[i] = 0;
3632  else if( basisStatusRows[i] == SPxSolver::FIXED )
3633  {
3634  assert(lhsRational(i) == rhsRational(i));
3635  basicPrimalRhs[i] = lhsRational(i);
3636  }
3637  else if( basisStatusRows[i] == SPxSolver::UNDEFINED )
3638  {
3639  MSG_INFO1( spxout, spxout << "Undefined basis status of row in rational factorization.\n" );
3640  error = true;
3641  goto TERMINATE;
3642  }
3643  else
3644  {
3645  assert(basisStatusRows[i] == SPxSolver::BASIC);
3646  MSG_INFO1( spxout, spxout << "Too many basic rows in rational factorization.\n" );
3647  error = true;
3648  goto TERMINATE;
3649  }
3650  }
3651  numBasicRows = j;
3652 
3653  for( int i = 0; i < basisStatusCols.size(); i++ )
3654  {
3655  if( basisStatusCols[i] == SPxSolver::BASIC && j < matrixdim )
3656  {
3657  basicDualRhs[j] = objRational(i);
3658  if( loadMatrix )
3659  _rationalLUSolverBind[j] = i;
3660  j++;
3661  }
3662  else if( basisStatusCols[i] == SPxSolver::ON_LOWER )
3663  basicPrimalRhs.multAdd(-lowerRational(i), colVectorRational(i));
3664  else if( basisStatusCols[i] == SPxSolver::ON_UPPER )
3665  basicPrimalRhs.multAdd(-upperRational(i), colVectorRational(i));
3666  else if( basisStatusCols[i] == SPxSolver::ZERO )
3667  {}
3668  else if( basisStatusCols[i] == SPxSolver::FIXED )
3669  {
3670  assert(lowerRational(i) == upperRational(i));
3671  basicPrimalRhs.multAdd(-lowerRational(i), colVectorRational(i));
3672  }
3673  else if( basisStatusCols[i] == SPxSolver::UNDEFINED )
3674  {
3675  MSG_INFO1( spxout, spxout << "Undefined basis status of column in rational factorization.\n" );
3676  error = true;
3677  goto TERMINATE;
3678  }
3679  else
3680  {
3681  assert(basisStatusCols[i] == SPxSolver::BASIC);
3682  MSG_INFO1( spxout, spxout << "Too many basic columns in rational factorization.\n" );
3683  error = true;
3684  goto TERMINATE;
3685  }
3686  }
3687 
3688  if( j != matrixdim )
3689  {
3690  MSG_INFO1( spxout, spxout << "Too few basic entries in rational factorization.\n" );
3691  error = true;
3692  goto TERMINATE;
3693  }
3694 
3695  // load and factorize rational basis matrix
3696  if( loadMatrix )
3698 
3700  {
3701  stoppedTime = true;
3702  return;
3703  }
3705  {
3706  error = true;
3707  return;
3708  }
3710 
3711  // solve for primal solution
3714  else
3716  _rationalLUSolver.solveRight(basicPrimal, basicPrimalRhs);
3717 
3718  // record statistics
3721 
3722  if( _isSolveStopped(stoppedTime, stoppedIter) )
3723  {
3724  MSG_INFO2( spxout, spxout << "Rational factorization hit time limit while solving for primal.\n" );
3725  return;
3726  }
3727 
3728  // check bound violation on basic rows and columns
3729  j = 0;
3730  primalViolation = 0;
3731  primalFeasible = true;
3732  for( int i = 0; i < basisStatusRows.size(); i++ )
3733  {
3734  if( basisStatusRows[i] == SPxSolver::BASIC )
3735  {
3736  assert(j < matrixdim);
3737  assert(_rationalLUSolverBind[j] == -1 - i);
3738  violation = lhsRational(i);
3739  violation += basicPrimal[j];
3740  if( violation > primalViolation )
3741  {
3742  primalFeasible = false;
3743  primalViolation = violation;
3744  }
3745  violation = rhsRational(i);
3746  violation += basicPrimal[j];
3747  violation *= -1;
3748  if( violation > primalViolation )
3749  {
3750  primalFeasible = false;
3751  primalViolation = violation;
3752  }
3753  j++;
3754  }
3755  }
3756  for( int i = 0; i < basisStatusCols.size(); i++ )
3757  {
3758  if( basisStatusCols[i] == SPxSolver::BASIC )
3759  {
3760  assert(j < matrixdim);
3761  assert(_rationalLUSolverBind[j] == i);
3762  if( basicPrimal[j] < lowerRational(i) )
3763  {
3764  violation = lowerRational(i);
3765  violation -= basicPrimal[j];
3766  if( violation > primalViolation )
3767  {
3768  primalFeasible = false;
3769  primalViolation = violation;
3770  }
3771  }
3772  if( basicPrimal[j] > upperRational(i) )
3773  {
3774  violation = basicPrimal[j];
3775  violation -= upperRational(i);
3776  if( violation > primalViolation )
3777  {
3778  primalFeasible = false;
3779  primalViolation = violation;
3780  }
3781  }
3782  j++;
3783  }
3784  }
3785 
3786  if( !primalFeasible )
3787  {
3788  MSG_INFO1( spxout, spxout << "Rational solution primal infeasible.\n" );
3789  }
3790 
3791  // solve for dual solution
3794  else
3796  _rationalLUSolver.solveLeft(basicDual, basicDualRhs);
3797 
3798  // record statistics
3801 
3802  if( _isSolveStopped(stoppedTime, stoppedIter) )
3803  {
3804  MSG_INFO2( spxout, spxout << "Rational factorization hit time limit while solving for dual.\n" );
3805  return;
3806  }
3807 
3808  // check dual violation on nonbasic rows
3809  dualViolation = 0;
3810  dualFeasible = true;
3811  for( int i = 0; i < basisStatusRows.size(); i++ )
3812  {
3813  if( _rowTypes[i] == RANGETYPE_FIXED
3814  && (basisStatusRows[i] == SPxSolver::ON_LOWER || basisStatusRows[i] == SPxSolver::ON_UPPER) )
3815  {
3816  assert(lhsRational(i) == rhsRational(i));
3817  basisStatusRows[i] = SPxSolver::FIXED;
3818  }
3819 
3820  assert(basisStatusRows[i] != SPxSolver::BASIC || basicDual[i] == 0);
3821  if( basisStatusRows[i] == SPxSolver::BASIC || basisStatusRows[i] == SPxSolver::FIXED )
3822  continue;
3823  else if( basicDual[i] < 0 )
3824  {
3825  if( ((maximizing && basisStatusRows[i] != SPxSolver::ON_LOWER) || (!maximizing && basisStatusRows[i] != SPxSolver::ON_UPPER))
3826  && (basisStatusRows[i] != SPxSolver::ZERO || rhsRational(i) != 0) )
3827  {
3828  dualFeasible = false;
3829  violation = -basicDual[i];
3830  if( violation > dualViolation )
3831  dualViolation = violation;
3832  MSG_DEBUG( spxout << "negative dual multliplier for row " << i
3833  << " with dual " << rationalToString(basicDual[i])
3834  << " and status " << basisStatusRows[i]
3835  << " and [lhs,rhs] = [" << rationalToString(lhsRational(i)) << "," << rationalToString(rhsRational(i)) << "]"
3836  << "\n" );
3837  }
3838  }
3839  else if( basicDual[i] > 0 )
3840  {
3841  if( ((maximizing && basisStatusRows[i] != SPxSolver::ON_UPPER) || (!maximizing && basisStatusRows[i] != SPxSolver::ON_LOWER))
3842  && (basisStatusRows[i] != SPxSolver::ZERO || lhsRational(i) == 0) )
3843  {
3844  dualFeasible = false;
3845  if( basicDual[i] > dualViolation )
3846  dualViolation = basicDual[i];
3847  MSG_DEBUG( spxout << "positive dual multliplier for row " << i
3848  << " with dual " << rationalToString(basicDual[i])
3849  << " and status " << basisStatusRows[i]
3850  << " and [lhs,rhs] = [" << rationalToString(lhsRational(i)) << "," << rationalToString(rhsRational(i)) << "]"
3851  << "\n" );
3852  }
3853  }
3854  }
3855 
3856  // check reduced cost violation on nonbasic columns
3857  for( int i = 0; i < basisStatusCols.size(); i++ )
3858  {
3859  if( _colTypes[i] == RANGETYPE_FIXED
3860  && (basisStatusCols[i] == SPxSolver::ON_LOWER || basisStatusCols[i] == SPxSolver::ON_UPPER) )
3861  {
3862  assert(lowerRational(i) == upperRational(i));
3863  basisStatusCols[i] = SPxSolver::FIXED;
3864  }
3865 
3866 #ifdef SOPLEX_WITH_GMP
3867  assert(basisStatusCols[i] != SPxSolver::BASIC || basicDual * colVectorRational(i) == objRational(i));
3868 #endif
3869  if( basisStatusCols[i] == SPxSolver::BASIC || basisStatusCols[i] == SPxSolver::FIXED )
3870  continue;
3871  else
3872  {
3873  _workSol._redCost[i] = basicDual * colVectorRational(i);
3874  _workSol._redCost[i] -= objRational(i);
3875  if( _workSol._redCost[i] > 0 )
3876  {
3877  if( ((maximizing && basisStatusCols[i] != SPxSolver::ON_LOWER) || (!maximizing && basisStatusCols[i] != SPxSolver::ON_UPPER))
3878  && (basisStatusCols[i] != SPxSolver::ZERO || upperRational(i) != 0) )
3879  {
3880  dualFeasible = false;
3881  if( _workSol._redCost[i] > dualViolation )
3882  dualViolation = _workSol._redCost[i];
3883  }
3884  _workSol._redCost[i] *= -1;
3885  }
3886  else if( _workSol._redCost[i] < 0 )
3887  {
3888  _workSol._redCost[i] *= -1;
3889  if( ((maximizing && basisStatusCols[i] != SPxSolver::ON_UPPER) || (!maximizing && basisStatusCols[i] != SPxSolver::ON_LOWER))
3890  && (basisStatusCols[i] != SPxSolver::ZERO || lowerRational(i) != 0) )
3891  {
3892  dualFeasible = false;
3893  if( _workSol._redCost[i] > dualViolation )
3894  dualViolation = _workSol._redCost[i];
3895  }
3896  }
3897  else
3898  _workSol._redCost[i] *= -1;
3899  }
3900  }
3901 
3902  if( !dualFeasible )
3903  {
3904  MSG_INFO1( spxout, spxout << "Rational solution dual infeasible.\n" );
3905  }
3906 
3907  // store solution
3908  optimal = primalFeasible && dualFeasible;
3909  if( optimal || boolParam(SoPlex::RATFACJUMP) )
3910  {
3911  _hasBasis = true;
3912  if( &basisStatusRows != &_basisStatusRows )
3913  _basisStatusRows = basisStatusRows;
3914  if( &basisStatusCols != &_basisStatusCols )
3915  _basisStatusCols = basisStatusCols;
3916 
3917  sol._primal.reDim(numColsRational());
3918  j = numBasicRows;
3919  for( int i = 0; i < basisStatusCols.size(); i++ )
3920  {
3921  if( basisStatusCols[i] == SPxSolver::BASIC )
3922  {
3923  assert(j < matrixdim);
3924  assert(_rationalLUSolverBind[j] == i);
3925  sol._primal[i] = basicPrimal[j];
3926  j++;
3927  }
3928  else if( basisStatusCols[i] == SPxSolver::ON_LOWER )
3929  sol._primal[i] = lowerRational(i);
3930  else if( basisStatusCols[i] == SPxSolver::ON_UPPER )
3931  sol._primal[i] = upperRational(i);
3932  else if( basisStatusCols[i] == SPxSolver::ZERO )
3933  sol._primal[i] = 0;
3934  else if( basisStatusCols[i] == SPxSolver::FIXED )
3935  {
3936  assert(lowerRational(i) == upperRational(i));
3937  sol._primal[i] = lowerRational(i);
3938  }
3939  else
3940  {
3941  assert(basisStatusCols[i] == SPxSolver::UNDEFINED);
3942  MSG_INFO1( spxout, spxout << "Undefined basis status of column in rational factorization.\n" );
3943  error = true;
3944  goto TERMINATE;
3945  }
3946  }
3947  sol._slacks.reDim(numRowsRational());
3949  sol._isPrimalFeasible= true;
3950 
3951  sol._dual = basicDual;
3952  for( int i = 0; i < numColsRational(); i++ )
3953  {
3954  if( basisStatusCols[i] == SPxSolver::BASIC )
3955  sol._redCost[i] = 0;
3956  else if( basisStatusCols[i] == SPxSolver::FIXED )
3957  {
3958  sol._redCost[i] = basicDual * colVectorRational(i);
3959  sol._redCost[i] -= objRational(i);
3960  sol._redCost[i] *= -1;
3961  }
3962  else
3963  sol._redCost[i] = _workSol._redCost[i];
3964  }
3965  sol._isDualFeasible = true;
3966  }
3967 
3968  TERMINATE:
3969  // stop rational solving time
3971  return;
3972  }
3973 
3974  /// attempts rational reconstruction of primal-dual solution
3976  {
3977  bool success;
3978  bool isSolBasic;
3979  DIdxSet basicIndices(numColsRational());
3980 
3981  success = false;
3982  isSolBasic = true;
3983 
3984  if( !sol.isPrimalFeasible() || !sol.isDualFeasible() )
3985  return success;
3986 
3987  // start timing and increment statistics counter
3990 
3991  // reconstruct primal vector
3992  _workSol._primal = sol._primal;
3993  for( int j = 0; j < numColsRational(); ++j )
3994  {
3995  if( basisStatusCols[j] == SPxSolver::BASIC )
3996  basicIndices.addIdx(j);
3997  }
3998 
3999  success = reconstructVector(_workSol._primal, denomBoundSquared, &basicIndices);
4000 
4001  if( !success )
4002  {
4003  MSG_INFO1( spxout, spxout << "Rational reconstruction of primal solution failed.\n" );
4005  return success;
4006  }
4007 
4008  MSG_DEBUG( spxout << "Rational reconstruction of primal solution successful.\n" );
4009 
4010  // check violation of bounds
4011  for( int c = numColsRational() - 1; c >= 0; c-- )
4012  {
4013  // we want to notify the user whether the reconstructed solution is basic; otherwise, this would be redundant
4014  SPxSolver::VarStatus& basisStatusCol = _basisStatusCols[c];
4015  if( (basisStatusCol == SPxSolver::FIXED && _workSol._primal[c] != lowerRational(c))
4016  || (basisStatusCol == SPxSolver::ON_LOWER && _workSol._primal[c] != lowerRational(c))
4017  || (basisStatusCol == SPxSolver::ON_UPPER && _workSol._primal[c] != upperRational(c))
4018  || (basisStatusCol == SPxSolver::ZERO && _workSol._primal[c] != 0)
4019  || (basisStatusCol == SPxSolver::UNDEFINED) )
4020  {
4021  isSolBasic = false;
4022  }
4023 
4024  if( _lowerFinite(_colTypes[c]) && _workSol._primal[c] < lowerRational(c) )
4025  {
4026  MSG_DEBUG( std::cout << "Lower bound of variable " << c << " violated by " << rationalToString(lowerRational(c) - _workSol._primal[c]) << "\n" );
4027  MSG_INFO1( spxout, spxout << "Reconstructed solution primal infeasible (1).\n" );
4029  return false;
4030  }
4031 
4032  if( _upperFinite(_colTypes[c]) && _workSol._primal[c] > upperRational(c) )
4033  {
4034  MSG_DEBUG( std::cout << "Upper bound of variable " << c << " violated by " << rationalToString(_workSol._primal[c] - upperRational(c)) << "\n" );
4035  MSG_INFO1( spxout, spxout << "Reconstructed solution primal infeasible (2).\n" );
4037  return false;
4038  }
4039  }
4040 
4041  // compute slacks
4042  ///@todo we should compute them one by one so we can abort when encountering an infeasibility
4045 
4046  // check violation of sides
4047  for( int r = numRowsRational() - 1; r >= 0; r-- )
4048  {
4049  // we want to notify the user whether the reconstructed solution is basic; otherwise, this would be redundant
4050  SPxSolver::VarStatus& basisStatusRow = _basisStatusRows[r];
4051  if( (basisStatusRow == SPxSolver::FIXED && _workSol._slacks[r] != lhsRational(r))
4052  || (basisStatusRow == SPxSolver::ON_LOWER && _workSol._slacks[r] != lhsRational(r))
4053  || (basisStatusRow == SPxSolver::ON_UPPER && _workSol._slacks[r] != rhsRational(r))
4054  || (basisStatusRow == SPxSolver::ZERO && _workSol._slacks[r] != 0)
4055  || (basisStatusRow == SPxSolver::UNDEFINED) )
4056  {
4057  isSolBasic = false;
4058  }
4059 
4060  if( _lowerFinite(_rowTypes[r]) && _workSol._slacks[r] < lhsRational(r) )
4061  {
4062  MSG_DEBUG( std::cout << "Lhs of row " << r << " violated by " << rationalToString(lhsRational(r) - _workSol._slacks[r]) << "\n" );
4063  MSG_INFO1( spxout, spxout << "Reconstructed solution primal infeasible (3).\n" );
4065  return false;
4066  }
4067 
4068  if( _upperFinite(_rowTypes[r]) && _workSol._slacks[r] > rhsRational(r) )
4069  {
4070  MSG_DEBUG( std::cout << "Rhs of row " << r << " violated by " << rationalToString(_workSol._slacks[r] - rhsRational(r)) << "\n" );
4071  MSG_INFO1( spxout, spxout << "Reconstructed solution primal infeasible (4).\n" );
4073  return false;
4074  }
4075  }
4076 
4077  // reconstruct dual vector
4078  _workSol._dual = sol._dual;
4079 
4080  success = reconstructVector(_workSol._dual, denomBoundSquared);
4081 
4082  if( !success )
4083  {
4084  MSG_INFO1( spxout, spxout << "Rational reconstruction of dual solution failed.\n" );
4086  return success;
4087  }
4088 
4089  MSG_DEBUG( spxout << "Rational reconstruction of dual vector successful.\n" );
4090 
4091  // check dual multipliers before reduced costs because this check is faster since it does not require the
4092  // computation of reduced costs
4093  const bool maximizing = (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE);
4094  for( int r = numRowsRational() - 1; r >= 0; r-- )
4095  {
4096  int sig = sign(_workSol._dual[r]);
4097 
4098  if( (!maximizing && sig > 0) || (maximizing && sig < 0) )
4099  {
4100  if( !_lowerFinite(_rowTypes[r]) || _workSol._slacks[r] > lhsRational(r) )
4101  {
4102  MSG_DEBUG( std::cout << "complementary slackness violated by row " << r
4103  << " with dual " << rationalToString(_workSol._dual[r])
4104  << " and slack " << rationalToString(_workSol._slacks[r])
4105  << " not at lhs " << rationalToString(lhsRational(r))
4106  << "\n" );
4107  MSG_INFO1( spxout, spxout << "Reconstructed solution dual infeasible (1).\n" );
4109  return false;
4110  }
4111 
4113  {
4115  isSolBasic = false;
4116  else
4118  }
4119  }
4120  else if( (!maximizing && sig < 0) || (maximizing && sig > 0) )
4121  {
4122  if( !_upperFinite(_rowTypes[r]) || _workSol._slacks[r] < rhsRational(r) )
4123  {
4124  MSG_DEBUG( std::cout << "complementary slackness violated by row " << r
4125  << " with dual " << rationalToString(_workSol._dual[r])
4126  << " and slack " << rationalToString(_workSol._slacks[r])
4127  << " not at rhs " << rationalToString(rhsRational(r))
4128  << "\n" );
4129  MSG_INFO1( spxout, spxout << "Reconstructed solution dual infeasible (2).\n" );
4131  return false;
4132  }
4133 
4135  {
4137  isSolBasic = false;
4138  else
4140  }
4141  }
4142  }
4143 
4144  // compute reduced cost vector; we assume that the objective function vector has less nonzeros than the reduced
4145  // cost vector, and so multiplying with -1 first and subtracting the dual activity should be faster than adding
4146  // the dual activity and negating afterwards
4147  ///@todo we should compute them one by one so we can abort when encountering an infeasibility
4151 
4152  // check reduced cost violation
4153  for( int c = numColsRational() - 1; c >= 0; c-- )
4154  {
4155  int sig = sign(_workSol._redCost[c]);
4156 
4157  if( (!maximizing && sig > 0) || (maximizing && sig < 0) )
4158  {
4159  if( !_lowerFinite(_colTypes[c]) || _workSol._primal[c] > lowerRational(c) )
4160  {
4161  MSG_DEBUG( std::cout << "complementary slackness violated by column " << c
4162  << " with reduced cost " << rationalToString(_workSol._redCost[c])
4163  << " and value " << rationalToString(_workSol._primal[c])
4164  << " not at lower bound " << rationalToString(lowerRational(c))
4165  << "\n" );
4166  MSG_INFO1( spxout, spxout << "Reconstructed solution dual infeasible (3).\n" );
4168  return false;
4169  }
4170 
4172  {
4174  isSolBasic = false;
4175  else
4177  }
4178  }
4179  else if( (!maximizing && sig < 0) || (maximizing && sig > 0) )
4180  {
4181  if( !_upperFinite(_colTypes[c]) || _workSol._primal[c] < upperRational(c) )
4182  {
4183  MSG_DEBUG( std::cout << "complementary slackness violated by column " << c
4184  << " with reduced cost " << rationalToString(_workSol._redCost[c])
4185  << " and value " << rationalToString(_workSol._primal[c])
4186  << " not at upper bound " << rationalToString(upperRational(c))
4187  << "\n" );
4188  MSG_INFO1( spxout, spxout << "Reconstructed solution dual infeasible (4).\n" );
4190  return false;
4191  }
4192 
4194  {
4196  isSolBasic = false;
4197  else
4199  }
4200  }
4201  }
4202 
4203  // update solution
4204  sol._primal = _workSol._primal;
4205  sol._slacks = _workSol._slacks;
4206  sol._dual = _workSol._dual;
4207  sol._redCost = _workSol._redCost;
4208 
4209  if( !isSolBasic )
4210  {
4211  MSG_WARNING( spxout, spxout << "Warning: Reconstructed solution not basic.\n" );
4212  _hasBasis = false;
4213  }
4214 
4215  // stop timing
4217 
4218  return success;
4219  }
4220 } // namespace soplex
4221 #endif
const VectorBase< R > & rhs() const
Returns right hand side vector.
Definition: spxlpbase.h:219
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3909
int _lastSolveMode
Definition: soplex.h:1809
const VectorRational & rhsRational() const
returns right-hand side vector
Definition: soplex.cpp:1157
DVectorBase< R > _slacks
Definition: solbase.h:219
textbook ratio test without stabilization
Definition: soplex.h:1167
void _computeBasisInverseRational()
computes rational inverse of basis matrix as defined by _rationalLUSolverBind
int unbdRefinements
number of refinement steps during undboundedness test
Definition: statistics.h:114
virtual void removeRow(int i)
Removes i &#39;th row.
Definition: spxlpbase.h:884
Rational _rationalMaxscaleincr
Definition: soplex.h:1558
free variable fixed to zero.
Definition: spxsolver.h:194
DVectorRational _unboundedRhs
Definition: soplex.h:1620
bool isSetup() const
Returns setup status.
Definition: ssvectorbase.h:120
bool GE(Real a, Real b, Real eps=Param::epsilon())
returns true iff a >= b + eps
Definition: spxdefines.h:405
SolRational _workSol
Definition: soplex.h:1816
void reDim(int newdim, const bool setZero=true)
Resets DVectorBase&#39;s dimension to newdim.
Definition: dvectorbase.h:249
Rational & addProduct(const Rational &r, const Rational &s)
add product of two rationals
Definition: rational.cpp:3356
void _transformEquality()
introduces slack variables to transform inequality constraints into equations for both rational and r...
DVectorBase< R > _dualFarkas
Definition: solbase.h:223
Timer * syncTime
time for synchronization between real and rational LP (included in solving time)
Definition: statistics.h:92
Basis is not known to be dual nor primal feasible.
Definition: spxbasis.h:94
int feasRefinements
number of refinement steps during infeasibility test
Definition: statistics.h:113
No matrix has yet been loaded.
virtual void unscalePrimal(const SPxLPBase< Real > &lp, Vector &x) const
unscale dense primal solution vector given in x.
Definition: spxscaler.cpp:609
int numRowsReal() const
returns number of rows
Definition: soplex.cpp:793
virtual void changeLower(const Vector &newLower, bool scale=false)
The time limit has been hit.
const VectorBase< R > & upper() const
Returns upper bound vector.
Definition: spxlpbase.h:456
virtual Status getPrimal(Vector &vector) const
get solution vector for primal variables.
Definition: spxsolve.cpp:1562
upper limit on objective value
Definition: soplex.h:1298
THREADLOCAL const Real infinity
Definition: spxdefines.cpp:26
void _transformUnbounded()
transforms LP to unboundedness problem by moving the objective function to the constraints, changing right-hand side and bounds to zero, and adding an auxiliary variable for the decrease in the objective function
general zero tolerance
Definition: soplex.h:1277
LPRowBase< Rational > LPRowRational
Definition: lprow.h:29
Result
Result of the simplification.
Definition: spxsimplifier.h:81
const SPxRatioTester * ratiotester() const
return loaded SPxRatioTester.
Definition: spxsolver.h:1747
type of ratio test
Definition: soplex.h:980
the problem was so much simplified that it vanished
Definition: spxsimplifier.h:87
continue iterative refinement with exact basic solution if not optimal?
Definition: soplex.h:919
void setBasis(const VarStatus rows[], const VarStatus cols[])
set the lp solver&#39;s basis.
Definition: spxsolver.cpp:1863
virtual Result simplify(SPxLP &lp, Real eps, Real delta)=0
simplify SPxLP lp with identical primal and dual feasibility tolerance.
DVectorRational _feasLhs
Definition: soplex.h:1623
type of computational form, i.e., column or row representation
Definition: soplex.h:941
int stallRefinements
number of refinement steps without pivots
Definition: statistics.h:111
T * get_ptr()
get a C pointer to the data.
Definition: dataarray.h:110
virtual void removeRowRange(int start, int end, int perm[]=0)
Removes rows from start to end (including both).
Definition: spxlpbase.h:954
int size() const
Number of used indices.
Definition: svectorbase.h:152
int numRowsRational() const
returns number of rows
Definition: soplex.cpp:1085
SPxLPRational * _rationalLP
Definition: soplex.h:1612
Status getBasis(VarStatus rows[], VarStatus cols[], const int rowsSize=-1, const int colsSize=-1) const
get current basis, and return solver status.
Definition: spxsolver.cpp:1790
SPxSolver::Status _solveRealStable(bool acceptUnbounded, bool acceptInfeasible, VectorReal &primal, VectorReal &dual, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, bool &returnedBasis, const bool forceNoSimplifier=false)
solves real LP with recovery mechanism
Real feastol() const
allowed primal feasibility tolerance.
Definition: spxsolver.h:777
time limit in seconds (INFTY if unlimited)
Definition: soplex.h:1292
Rational _rationalFeastol
Definition: soplex.h:1556
DVectorBase< R > _primalRay
Definition: solbase.h:220
modified Harris ratio test
Definition: soplex.h:1173
DVectorBase< R > _redCost
Definition: solbase.h:222
int getFactorCount() const
number of factorizations performed
virtual void clearRowObjs()
Definition: spxsolver.h:951
primal feasibility tolerance
Definition: soplex.h:1271
void getObj(VectorBase< R > &pobj) const
Gets objective vector.
Definition: spxlpbase.h:394
void setType(Type tp)
set LEAVE or ENTER algorithm.
Definition: spxsolver.cpp:169
bound flipping ratio test for long steps in the dual simplex
Definition: soplex.h:1176
DVectorRational _feasRhs
Definition: soplex.h:1624
DVectorRational _feasLower
Definition: soplex.h:1625
solve() aborted due to iteration limit.
Definition: spxsolver.h:213
SPxScaler * _scaler
Definition: soplex.h:1591
virtual void changeUpper(const Vector &newUpper, bool scale=false)
mode for synchronizing real and rational LP
Definition: soplex.h:983
bool hasDualFarkas() const
is a dual farkas ray available?
Definition: solbase.h:110
void _optimizeRational()
solves rational LP
void setValue(int i, R x)
Sets i &#39;th element to x.
Definition: ssvectorbase.h:218
virtual void unscaleRedCost(const SPxLPBase< Real > &lp, Vector &r) const
unscale dense reduced cost vector given in r.
Definition: spxscaler.cpp:645
void _transformFeasibility()
transforms LP to feasibility problem by removing the objective function, shifting variables...
Abstract ratio test base class.Class SPxRatioTester is the virtual base class for computing the ratio...
virtual void unscaleDual(const SPxLPBase< Real > &lp, Vector &pi) const
unscale dense dual solution vector given in pi.
Definition: spxscaler.cpp:633
should cycling solutions be accepted during iterative refinement?
Definition: soplex.h:910
void _disableSimplifierAndScaler()
disables simplifier and scaler
Definition: soplex.cpp:7965
DataArray< SPxSolver::VarStatus > _storedBasisStatusCols
Definition: soplex.h:1634
void add(const LPColBase< R > &pcol)
Definition: lpcolsetbase.h:255
Real lowerReal(int i) const
returns lower bound of column i
Definition: soplex.cpp:995
unsigned int _hasPrimalRay
Definition: solbase.h:228
Implementation of Sparse Linear Solver with Rational precision.
void _performFeasIRStable(SolRational &sol, bool &withDualFarkas, bool &stopped, bool &stoppedIter, bool &error)
performs iterative refinement on the auxiliary problem for testing feasibility
void _storeBasis()
store basis
Rational & subProduct(const Rational &r, const Rational &s)
subtract product of two rationals
Definition: rational.cpp:3365
Real upperReal(int i) const
returns upper bound of column i
Definition: soplex.cpp:968
Rational & invert()
inversion
Definition: rational.cpp:3392
int refinements
number of refinement steps
Definition: statistics.h:110
variable fixed to identical bounds.
Definition: spxsolver.h:193
DVectorReal _manualObj
Definition: soplex.h:1603
objective sense
Definition: soplex.h:938
virtual void removeCol(int i)
Removes i &#39;th column.
Definition: spxlpbase.h:981
LP has been proven to be primal infeasible.
Definition: spxsolver.h:222
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:254
SPxSolver::Status _solveRealForRational(bool fromscratch, VectorReal &primal, VectorReal &dual, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, bool &returnedBasis)
solves real LP during iterative refinement
void _untransformUnbounded(SolRational &sol, bool unbounded)
undoes transformation to unboundedness problem
void dump() const
Prints out status.
Definition: spxdesc.cpp:113
Ids for LP columns.Class SPxColId provides DataKeys for the column indices of an SPxLP.
Definition: spxid.h:36
int intParam(const IntParam param) const
returns integer parameter value
Definition: soplex.cpp:5534
void setOpttol(Real d)
set parameter opttol.
Definition: spxsolver.cpp:940
minimum number of stalling refinements since last pivot to trigger rational factorization ...
Definition: soplex.h:1001
int sign(const Rational &r)
Sign function; returns 1 if r > 0, 0 if r = 0, and -1 if r < 0.
Definition: rational.cpp:3922
Wrapper for GMP type mpq_class.We wrap mpq_class so that we can replace it by a double type if GMP is...
Definition: rational.h:45
Real rhsReal(int i) const
returns right-hand side of row i
Definition: soplex.cpp:896
should a rational factorization be performed after iterative refinement?
Definition: soplex.h:894
const SPxPricer * pricer() const
return loaded SPxPricer.
Definition: spxsolver.h:1737
LPColBase< Real > LPColReal
Definition: lpcol.h:30
Rational _rationalPosInfty
Definition: soplex.h:1554
Rational _rationalOpttol
Definition: soplex.h:1557
const VectorRational & lhsRational() const
returns left-hand side vector
Definition: soplex.cpp:1175
steepest edge pricer with exact initialization of norms
Definition: soplex.h:1160
int nRows() const
Returns number of rows in LP.
Definition: spxlpbase.h:151
Rational objRational(int i) const
returns objective value of column i
Definition: soplex.cpp:1284
void add(const SVectorBase< S > &vec)
Append nonzeros of sv.
Definition: dsvectorbase.h:216
DVectorRational _modLhs
Definition: soplex.h:1629
DVectorReal _manualLower
Definition: soplex.h:1599
virtual void changeRhs(const Vector &newRhs, bool scale=false)
virtual void start()=0
start timer, resume accounting user, system and real time.
Entering Simplex.
Definition: spxsolver.h:134
virtual Real stop()=0
stop timer, return accounted user time.
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
simplification could be done
Definition: spxsimplifier.h:83
const UnitVectorRational * _unitVectorRational(const int i)
returns pointer to a constant unit vector available until destruction of the SoPlex class ...
Definition: soplex.cpp:8318
virtual Status getDualfarkas(Vector &vector) const
get dual farkas proof of infeasibility.
Definition: spxsolve.cpp:1703
LP is primal infeasible or unbounded.
Definition: spxsolver.h:223
Rational reconstruction of solution vector.
Leaving Simplex.
Definition: spxsolver.h:143
void _ensureDSVectorRationalMemory(DSVectorRational &vec, const int newmax) const
extends sparse vector to hold newmax entries if and only if it holds no more free entries ...
Definition: soplex.cpp:7150
DataArray< SPxSolver::VarStatus > _basisStatusCols
Definition: soplex.h:1812
DVectorRational _unboundedLower
Definition: soplex.h:1617
bool reconstructVector(VectorRational &input, const Rational &denomBoundSquared, const DIdxSet *indexSet)
Definition: ratrecon.cpp:227
nothing known about basis status (possibly due to a singular basis in transformed problem) ...
Definition: spxsolver.h:196
virtual void changeRowObj(const Vector &newObj, bool scale=false)
virtual void writeFile(const char *filename, const NameSet *rowNames=0, const NameSet *colNames=0, const DIdxSet *p_intvars=0) const
Write loaded LP to filename.
Definition: spxlpbase.h:1155
SPxStatus status() const
returns current SPxStatus.
Definition: spxbasis.h:425
DVectorReal _manualRhs
Definition: soplex.h:1602
DataArray< RangeType > _colTypes
Definition: soplex.h:1659
type of scaler
Definition: soplex.h:971
Real getSolveTime() const
time spent in solves
double Real
Definition: spxdefines.h:215
Rational _rationalPosone
Definition: soplex.h:1830
bool _isRealLPLoaded
Definition: soplex.h:1594
SLUFactorRational _rationalLUSolver
Definition: soplex.h:1613
void _solveRealLPAndRecordStatistics()
call floating-point solver and update statistics on iterations etc.
Definition: soplex.cpp:8019
DVectorBase< R > _primal
Definition: solbase.h:218
#define MSG_DEBUG(x)
Definition: spxdefines.h:129
Status status() const
Status of solution process.
Definition: spxsolve.cpp:1879
void setMarkowitz(Real m)
sets minimum Markowitz threshold.
Definition: slufactor.h:128
lower threshold in lifting (nonzero matrix coefficients with smaller absolute value will be reformula...
Definition: soplex.h:1310
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:236
virtual void changeMaxObj(const VectorBase< R > &newObj, bool scale=false)
Changes objective vector to newObj. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1289
Timer * rationalTime
time for rational LP solving (included in solving time)
Definition: statistics.h:94
int _beforeLiftCols
Definition: soplex.h:1638
bool _isConsistent() const
checks consistency
Definition: soplex.cpp:7193
void _performOptIRStable(SolRational &sol, bool acceptUnbounded, bool acceptInfeasible, int minRounds, bool &primalFeasible, bool &dualFeasible, bool &infeasible, bool &unbounded, bool &stopped, bool &stoppedIter, bool &error)
solves current problem with iterative refinement and recovery mechanism
dual simplex algorithm, i.e., leaving for column and entering for row representation ...
Definition: soplex.h:1058
LP has been solved to optimality.
Definition: spxsolver.h:220
void setTimeLimit(const Real limit)
set time limit on factorization
#define MSG_INFO2(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO2.
Definition: spxdefines.h:117
bool _upperFinite(const RangeType &rangeType) const
checks whether RangeType corresponds to finite upper bound
Definition: soplex.cpp:7305
bool _hasBasis
Definition: soplex.h:1818
unsigned int _hasDualFarkas
Definition: solbase.h:230
void append(const T &t)
append element t.
Definition: dataarray.h:121
LPRowBase< Real > LPRowReal
Definition: lprow.h:28
void _restoreLPReal()
restores objective, bounds, and sides of real LP
DVectorBase< Rational > DVectorRational
Definition: dvector.h:30
void _project(SolRational &sol)
undoes lifting
Class for collecting statistical information.
void clearNum(int n)
Sets n &#39;th nonzero element to 0 (index n must exist).
Definition: ssvectorbase.h:269
solve() aborted due to time limit.
Definition: spxsolver.h:212
void _performUnboundedIRStable(SolRational &sol, bool &hasUnboundedRay, bool &stopped, bool &stoppedIter, bool &error)
performs iterative refinement on the auxiliary problem for testing unboundedness
Rational _rationalNegone
Definition: soplex.h:1831
DVectorRational _feasObj
Definition: soplex.h:1622
an error occured.
Definition: spxsolver.h:204
void addIdx(int i)
adds index i to the index set
Definition: didxset.h:75
round scaling factors for iterative refinement to powers of two?
Definition: soplex.h:916
const T * get_const_ptr() const
get a const C pointer to the data.
Definition: dataarray.h:115
virtual void changeLhs(const Vector &newLhs, bool scale=false)
void _computeInfeasBox(SolRational &sol, bool transformed)
virtual void changeLower(const VectorBase< R > &newLower, bool scale=false)
Changes vector of lower bounds to newLower. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1325
Statistics * _statistics
statistics since last call to solveReal() or solveRational()
Definition: soplex.h:1541
virtual void changeRhs(const VectorBase< R > &newRhs, bool scale=false)
Changes right hand side vector for constraints to newRhs. scale determines whether the new data shoul...
Definition: spxlpbase.h:1460
LPColSetRational _slackCols
Definition: soplex.h:1616
type of simplifier
Definition: soplex.h:968
bool isPrimalFeasible() const
is the stored solution primal feasible?
Definition: solbase.h:51
R obj(int i) const
Returns objective value of column i.
Definition: spxlpbase.h:403
void solveRight(VectorRational &x, const VectorRational &b)
Solves .
DVectorRational _feasUpper
Definition: soplex.h:1626
const VectorBase< R > & lhs() const
Returns left hand side vector.
Definition: spxlpbase.h:253
void clear()
Clears vector.
Definition: ssvectorbase.h:599
virtual void addPrimalActivity(const SVectorBase< R > &primal, VectorBase< R > &activity) const
Updates activity of the rows for a given primal vector; activity does not need to be zero...
Definition: spxlpbase.h:1730
int numColsRational() const
returns number of columns
Definition: soplex.cpp:1094
Abstract pricer base class.Class SPxPricer is a pure virtual class defining the interface for pricer ...
Definition: spxpricer.h:46
bool _reconstructSolutionRational(SolRational &sol, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, const Rational &denomBoundSquared)
attempts rational reconstruction of primal-dual solution
virtual void getBasis(SPxSolver::VarStatus[], SPxSolver::VarStatus[], const int rowsSize=-1, const int colsSize=-1) const =0
get optimal basis.
RangeType _switchRangeType(const RangeType &rangeType) const
switches RANGETYPE_LOWER to RANGETYPE_UPPER and vice versa
Definition: soplex.cpp:7284
SLUFactor _slufactor
Definition: soplex.h:1567
variable set to its upper bound.
Definition: spxsolver.h:191
void setEpsilon(R eps)
Changes the non-zero epsilon, invalidating the setup. */.
Definition: ssvectorbase.h:110
Dynamic index set.Class DIdxSet provides dynamic IdxSet in the sense, that no restrictions are posed ...
Definition: didxset.h:42
virtual void changeBounds(const VectorBase< R > &newLower, const VectorBase< R > &newUpper, bool scale=false)
Changes variable bounds to newLower and newUpper. scale determines whether the new data should be sca...
Definition: spxlpbase.h:1397
Real realParam(const RealParam param) const
returns real parameter value
Definition: soplex.cpp:5544
Real luSolveTimeRational
time for solving linear systems in rational precision
Definition: statistics.h:100
primal infeasibility was detected
Definition: spxsimplifier.h:84
virtual Real time() const =0
DVectorRational _modUpper
Definition: soplex.h:1628
user sync of real and rational LP
Definition: soplex.h:1189
SPxLPBase< Rational > SPxLPRational
Definition: spxlp.h:37
SPxOut spxout
Definition: soplex.h:1441
infinity threshold
Definition: soplex.h:1289
algorithm is running
Definition: spxsolver.h:218
const SVectorRational & colVectorRational(int i) const
returns vector of column i
Definition: soplex.cpp:1220
const VectorBase< R > & maxRowObj() const
Definition: spxlpbase.h:297
int index(int n) const
Returns index of the n &#39;th nonzero element.
Definition: ssvectorbase.h:174
SPxDefaultRT _ratiotesterTextbook
Definition: soplex.h:1583
Status load(const SVectorRational *vec[], int dim)
virtual const Vector & unsimplifiedPrimal()=0
returns a reference to the unsimplified primal solution.
virtual void loadLP(const SPxLP &LP, bool initSlackBasis=true)
copy LP.
Definition: spxsolver.cpp:68
variable set to its lower bound.
Definition: spxsolver.h:192
LPColBase< Rational > LPColRational
Definition: lpcol.h:31
Real lhsReal(int i) const
returns left-hand side of row i
Definition: soplex.cpp:923
Preconfigured SoPlex LP solver.
#define MSG_INFO3(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO3.
Definition: spxdefines.h:119
void add(int i, const R &v)
Append one nonzero (i,v).
Definition: svectorbase.h:272
Real markowitz()
returns Markowitz threshold.
Definition: slufactor.h:141
virtual void changeUpper(const VectorBase< R > &newUpper, bool scale=false)
Changes vector of upper bounds to newUpper. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1361
void reDim(int newdim)
Resets dimension to newdim.
Definition: ssvectorbase.h:565
int _beforeLiftRows
Definition: soplex.h:1637
lower and upper bound finite, but different
Definition: soplex.h:1653
int luFactorizationsRational
number of basis matrix factorizations in rational precision
Definition: statistics.h:108
bool isDualFeasible() const
is a dual solution available?
Definition: solbase.h:88
DVectorReal _manualLhs
Definition: soplex.h:1601
Timer * preprocessingTime
preprocessing time
Definition: statistics.h:90
equilibrium scaling on rows and columns
Definition: soplex.h:1113
bool _storedBasis
Definition: soplex.h:1636
virtual void changeObj(const VectorBase< R > &newObj, bool scale=false)
Changes objective vector to newObj. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1257
void _storeLPReal()
stores objective, bounds, and sides of real LP
Real getFactorTime() const
time spent in factorizations
Rational _rationalNegInfty
Definition: soplex.h:1555
virtual void addDualActivity(const SVectorBase< R > &dual, VectorBase< R > &activity) const
Updates "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need t...
Definition: spxlpbase.h:1753
VectorBase< R > & multAdd(const S &x, const VectorBase< T > &vec)
Addition of scaled vector.
Definition: vectorbase.h:410
lower bound equals upper bound
Definition: soplex.h:1656
virtual void addCol(const LPColBase< R > &col, bool scale=false)
Definition: spxlpbase.h:721
virtual void scale(SPxLPBase< Real > &lp, bool persistent=true)=0
scale SPxLP.
column representation Ax - s = 0, lower <= x <= upper, lhs <= s <= rhs
Definition: soplex.h:1045
Timer * reconstructionTime
time for rational reconstructions
Definition: statistics.h:95
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.
DVectorReal _manualUpper
Definition: soplex.h:1600
working tolerance for feasibility in floating-point solver during iterative refinement ...
Definition: soplex.h:1301
SPxLPReal * _realLP
Definition: soplex.h:1588
bool _lowerFinite(const RangeType &rangeType) const
checks whether RangeType corresponds to finite lower bound
Definition: soplex.cpp:7297
virtual void changeRange(const VectorBase< R > &newLhs, const VectorBase< R > &newRhs, bool scale=false)
Changes left and right hand side vectors. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1484
SPxDevexPR _pricerDevex
Definition: soplex.h:1580
void clear()
Remove all indices.
Definition: svectorbase.h:396
DataArray< RangeType > _rowTypes
Definition: soplex.h:1660
DVectorRational _modObj
Definition: soplex.h:1631
apply rational reconstruction after each iterative refinement?
Definition: soplex.h:913
solve() aborted due to detection of cycling.
Definition: spxsolver.h:211
type of pricer
Definition: soplex.h:977
Saving LPs in a form suitable for SoPlex.Class SPxLPBase provides the data structures required for sa...
Definition: spxlpbase.h:80
DSVectorBase< Real > DSVectorReal
Definition: dsvector.h:29
primal unboundedness was detected
Definition: spxsimplifier.h:86
working tolerance for optimality in floating-point solver during iterative refinement ...
Definition: soplex.h:1304
#define MSG_WARNING(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::WARNING.
Definition: spxdefines.h:113
virtual void unsimplify(const Vector &, const Vector &, const Vector &, const Vector &, const SPxSolver::VarStatus[], const SPxSolver::VarStatus[], bool isOptimal=true)=0
reconstructs an optimal solution for the unsimplified LP.
Real spxNextafter(Real x, Real y)
Definition: spxdefines.h:336
int iterations
number of iterations/pivots
Definition: statistics.h:101
const VectorBase< R > & maxObj() const
Returns objective vector for maximization problem.
Definition: spxlpbase.h:429
DVectorRational _unboundedLhs
Definition: soplex.h:1619
DSVectorRational _primalDualDiff
Definition: soplex.h:1632
void setup()
Initializes nonzero indices for elements with absolute values above epsilon and sets all other elemen...
Definition: ssvectorbase.h:132
DVectorRational _unboundedUpper
Definition: soplex.h:1618
const VectorRational & upperRational() const
returns upper bound vector
Definition: soplex.cpp:1229
SPxSolver _solver
Definition: soplex.h:1566
nothing known on loaded problem.
Definition: spxsolver.h:219
variable is basic.
Definition: spxsolver.h:195
type of algorithm, i.e., primal or dual
Definition: soplex.h:944
const SVectorBase< R > & rowVector(int i) const
Gets row vector of row i.
Definition: spxlpbase.h:204
virtual void addRow(const LPRowBase< R > &row, bool scale=false)
Definition: spxlpbase.h:560
virtual bool isUnsimplified() const
specifies whether an optimal solution has already been unsimplified.
DataArray< SPxSolver::VarStatus > _basisStatusRows
Definition: soplex.h:1811
virtual const Vector & unsimplifiedDual()=0
returns a reference to the unsimplified dual solution.
should dual infeasibility be tested in order to try to return a dual solution even if primal infeasib...
Definition: soplex.h:891
void _factorizeColumnRational(SolRational &sol, DataArray< SPxSolver::VarStatus > &basisStatusRows, DataArray< SPxSolver::VarStatus > &basisStatusCols, bool &stoppedTime, bool &stoppedIter, bool &error, bool &optimal)
factorizes rational basis matrix in column representation
Timer * solvingTime
solving time
Definition: statistics.h:89
int size() const
return nr. of elements.
Definition: dataarray.h:211
Type type() const
return current Type.
Definition: spxsolver.h:475
bool boolParam(const BoolParam param) const
returns boolean parameter value
Definition: soplex.cpp:5524
should lifting be used to reduce range of nonzero matrix coefficients?
Definition: soplex.h:885
virtual Status getRedCost(Vector &vector) const
get vector of reduced costs.
Definition: spxsolve.cpp:1642
DataArray< int > _rationalLUSolverBind
Definition: soplex.h:1614
#define MSG_INFO1(spxout, x)
Prints out message x if the verbosity level is at least SPxOut::INFO1.
Definition: spxdefines.h:115
virtual void removeColRange(int start, int end, int perm[]=0)
Removes columns from start to end (including both).
Definition: spxlpbase.h:1051
const SVectorBase< R > & colVector(int i) const
Returns column vector of column i.
Definition: spxlpbase.h:373
int nCols() const
Returns number of columns in LP.
Definition: spxlpbase.h:157
unsigned int _isPrimalFeasible
Definition: solbase.h:227
virtual void changeElement(int i, int j, const R &val, bool scale=false)
Changes LP element (i, j) to val. scale determines whether the new data should be scaled...
Definition: spxlpbase.h:1626
lower limit on objective value
Definition: soplex.h:1295
DSVectorRational _tauColVector
Definition: soplex.h:1621
DVectorRational _modLower
Definition: soplex.h:1627
bool _isSolveStopped(bool &stoppedTime, bool &stoppedIter) const
should solving process be stopped?
Definition: soplex.cpp:7219
virtual void changeLhs(const VectorBase< R > &newLhs, bool scale=false)
Changes left hand side vector for constraints to newLhs. scale determines whether the new data should...
Definition: spxlpbase.h:1428
void setFeastol(Real d)
set parameter feastol.
Definition: spxsolver.cpp:928
Timer * transformTime
time for transforming LPs (included in solving time)
Definition: statistics.h:93
void invalidate()
invalidate solution
Definition: solbase.h:209
void _restoreBasis()
restore basis
bool hasPrimalRay() const
is a primal unbounded ray available?
Definition: solbase.h:73
bool setIntParam(const IntParam param, const int value, const bool init=true)
sets integer parameter value; returns true on success
Definition: soplex.cpp:5628
SolRational _solRational
Definition: soplex.h:1815
std::string rationalToString(const Rational &r, const int precision)
convert rational number to string
Definition: rational.cpp:3452
geometric frequency at which to apply rational reconstruction
Definition: soplex.h:1322
Real opttol() const
allowed optimality, i.e., dual feasibility tolerance.
Definition: spxsolver.h:785
bool _hasSolRational
Definition: soplex.h:1820
void _enableSimplifierAndScaler()
enables simplifier and scaler according to current parameters
Definition: soplex.cpp:7919
primal simplex algorithm, i.e., entering for column and leaving for row representation ...
Definition: soplex.h:1055
DVectorRational _modRhs
Definition: soplex.h:1630
unsigned int _isDualFeasible
Definition: solbase.h:229
virtual void unscaleSlacks(const SPxLPBase< Real > &lp, Vector &s) const
unscale dense slack vector given in s.
Definition: spxscaler.cpp:621
bool setBoolParam(const BoolParam param, const bool value, const bool init=true)
sets boolean parameter value; returns true on success
Definition: soplex.cpp:5574
should LP be transformed to equality form before a rational solve?
Definition: soplex.h:888
const SVectorBase< R > & colVector(int i) const
Returns colVector of i &#39;th LPColBase in LPColSetBase.
Definition: lpcolsetbase.h:208
DVectorBase< R > _dual
Definition: solbase.h:221
virtual void setTerminationValue(Real value=infinity)
set objective limit.
Definition: spxsolver.cpp:1610
void clear()
Removes all LPColBases from the set.
Definition: lpcolsetbase.h:499
void solveLeft(VectorRational &x, const VectorRational &b)
Solves .
const SPxBasis & basis() const
Return current basis.
Definition: spxsolver.h:1727
virtual void changeObj(const Vector &newObj, bool scale=false)
scale determines whether the new data needs to be scaled according to the existing LP (persistent sca...
virtual void reLoad()
reload LP.
Definition: spxsolver.cpp:55
upper threshold in lifting (nonzero matrix coefficients with larger absolute value will be reformulat...
Definition: soplex.h:1313
DataArray< SPxSolver::VarStatus > _storedBasisStatusRows
Definition: soplex.h:1633
SPxLPReal _manualRealLP
Definition: soplex.h:1604
int numColsReal() const
returns number of columns
Definition: soplex.cpp:802
void resetCounters()
reset timers and counters
void reSize(int newsize)
reset size to newsize.
Definition: dataarray.h:223
Real luFactorizationTimeRational
time for factorizing bases matrices in rational precision
Definition: statistics.h:99
void _lift()
reduces matrix coefficient in absolute value by the lifting procedure of Thiele et al...
force iterative refinement
Definition: soplex.h:1212
const VectorBase< R > & lower() const
Returns (internal and possibly scaled) lower bound vector.
Definition: spxlpbase.h:483
SPxSolver::Status _status
Definition: soplex.h:1808
int num() const
Returns the number of LPColBases currently in LPColSetBase.
Definition: lpcolsetbase.h:82
virtual void computePrimalActivity(const VectorBase< R > &primal, VectorBase< R > &activity, const bool unscaled=true) const
Computes activity of the rows for a given primal vector; activity does not need to be zero...
Rational _rationalZero
Definition: soplex.h:1832
const Desc & desc() const
Definition: spxbasis.h:463
int rationalReconstructions
number of rational reconstructions performed
Definition: statistics.h:109
solve() aborted due to objective limit.
Definition: spxsolver.h:214
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:109
SPxSimplifier * _simplifier
Definition: soplex.h:1590
virtual void addCols(const LPColSetBase< R > &pset, bool scale=false)
Definition: spxlpbase.h:773
void _untransformEquality(SolRational &sol)
undoes transformation to equality form
int pivotRefinements
number of refinement steps until final basis is reached
Definition: statistics.h:112
virtual Status getDual(Vector &vector) const
get current solution vector for dual variables.
Definition: spxsolve.cpp:1611
Basis is singular, numerical troubles?
Definition: spxsolver.h:215
R value(int n) const
Returns value of the n &#39;th nonzero element.
Definition: ssvectorbase.h:182
virtual void factorize()
Factorize basis matrix.
Definition: spxsolver.cpp:547
upper bound is finite, lower bound is infinite
Definition: soplex.h:1650
LP has a usable Basis (maybe LP is changed).
Definition: spxsolver.h:217
dual infeasibility was detected
Definition: spxsimplifier.h:85
virtual Status getSlacks(Vector &vector) const
get vector of slack variables.
Definition: spxsolve.cpp:1721
void _untransformFeasibility(SolRational &sol, bool infeasible)
undoes transformation to feasibility problem
LP has been proven to be primal unbounded.
Definition: spxsolver.h:221
virtual void subDualActivity(const VectorBase< R > &dual, VectorBase< R > &activity) const
Updates "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need t...
Definition: spxlpbase.h:1771
No Problem has been loaded to the basis.
Definition: spxbasis.h:92
void setDelta(Real d)
set parameter delta, i.e., set feastol and opttol to same value.
Definition: spxsolver.cpp:952
const VectorRational & lowerRational() const
returns lower bound vector
Definition: soplex.cpp:1247
Rational & powRound()
round up to next power of two
Definition: rational.cpp:3401